使用 Intuit.Ipp.Data.Qbo.CustomerQuery 时,我可以添加一个名称过滤器来查询数据库以获取有效的特定公司名称。但是,如果客户名称中包含 & 符号,例如 B&H,则会引发“401 Unauthorized”错误。
在查看 Intuit.Ipp.Data.Qbo.CustomerQuery 查询中的问题并尝试回答后,我尝试按照 Jarred 的建议将过滤器值编码为“B&H”,这产生了相同的错误。我还尝试使用以下代码直接调用 API,但它也会产生相同的错误(除非我将过滤器值更改为没有 & 的客户)
public List<Intuit.Ipp.Data.Qbo.Customer> GetQboCustomers(DataServices dataServices)
{
StringBuilder requestXML = new StringBuilder();
StringBuilder responseXML = new StringBuilder();
string requestBody = "Filter=NAME :EQUALS: B&H";
HttpWebRequest httpWebRequest = WebRequest.Create(dataServices.ServiceContext.BaseUrl + "customers/v2/" + dataServices.ServiceContext.RealmId) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest));
requestXML.Append(requestBody);
UTF8Encoding encoding = new UTF8Encoding();
byte[] content = encoding.GetBytes(requestXML.ToString());
using (var stream = httpWebRequest.GetRequestStream())
{
stream.Write(content, 0, content.Length);
}
HttpWebResponse httpWebResponse = httpWebRequest.GetResponse() as HttpWebResponse;
using (Stream data = httpWebResponse.GetResponseStream())
{
Intuit.Ipp.Data.Qbo.SearchResults searchResults = (Intuit.Ipp.Data.Qbo.SearchResults)dataServices.ServiceContext.Serializer.Deserialize<Intuit.Ipp.Data.Qbo.SearchResults>(new StreamReader(data).ReadToEnd());
if (searchResults.Count > 0)
{
return ((Intuit.Ipp.Data.Qbo.Customers)searchResults.CdmCollections).Customer.ToList();
}
else
{
return new List<Intuit.Ipp.Data.Qbo.Customer>();
}
}
}
protected string GetDevDefinedOAuthHeader(HttpWebRequest webRequest)
{
OAuthConsumerContext consumerContext = new OAuthConsumerContext
{
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
};
consumerContext.UseHeaderForOAuthParameters = true;
//URIs not used
OAuthSession oSession = new OAuthSession(consumerContext, "https://www.example.com",
"https://www.example.com",
"https://www.example.com");
oSession.AccessToken = new TokenBase
{
Token = accessToken,
ConsumerKey = consumerKey,
TokenSecret = accessTokenSecret
};
IConsumerRequest consumerRequest = oSession.Request();
consumerRequest = ConsumerRequestExtensions.ForMethod(consumerRequest, webRequest.Method);
consumerRequest = ConsumerRequestExtensions.ForUri(consumerRequest, webRequest.RequestUri);
if (webRequest.Headers.Count > 0)
{
ConsumerRequestExtensions.AlterContext(consumerRequest, context => context.Headers = webRequest.Headers);
if (webRequest.Headers[HttpRequestHeader.ContentType] == "application/x-www-form-urlencoded")
{
formParameters.Add("Filter", "NAME :EQUALS: B&H");
consumerRequest = consumerRequest.WithFormParameters(formParameters);
}
}
consumerRequest = consumerRequest.SignWithToken();
return consumerRequest.Context.GenerateOAuthParametersForHeader();
}
我已经简化了上面的代码,以便您可以轻松识别我要传递的查询值。如果 B&H 更改为 BH,则查询执行没有问题,因此它不是授权问题。