使用 QuickBooks Online (QBO) Intuit 合作伙伴平台 (IPP) DevKit 查询所有未结余额发票
Posted
技术标签:
【中文标题】使用 QuickBooks Online (QBO) Intuit 合作伙伴平台 (IPP) DevKit 查询所有未结余额发票【英文标题】:Query for All Invoices With Open Balances using QuickBooks Online (QBO) Intuit Partner Platform (IPP) DevKit 【发布时间】:2013-01-14 17:51:24 【问题描述】:我正在尝试使用 IPP 查询所有未结余额的发票,但我一直收到 0 个结果。我在代码中做错了吗?
这是我尝试使用应用过滤的 C# 代码 sn-p
InvoiceQuery qboInvoiceQuery = new InvoiceQuery();
int iMaxPageNumber = QUERY_MAX_PAGE_NUMBER; // A Constant with the Maximum Page Number allowed in a query
int iResultsPerPage = QUERY_MAX_NUM_PER_PAGE_INVOICE; // A Constant with the Maximum Results per page
// Paging Information
qboInvoiceQuery.PageNumber = QUERY_START_PAGE_NUMBER;
qboInvoiceQuery.ResultsPerPage = iResultsPerPage;
#region Query Filtering
//////////////////////////////////////////////
// initial filtering via Query Criteria //
//////////////////////////////////////////////
// Get only Open (Unpaid) Invoices
qboInvoiceQuery.OpenBalance = (decimal)0.00;
qboInvoiceQuery.SpecifyOperatorOption(FilterProperty.OpenBalance, FilterOperatorType.AFTER);
//////////////////////////////////////////////
// END initial filtering via Query Criteria //
//////////////////////////////////////////////
#endregion
// Complete the Query calls to build the list
IEnumerable<Invoice> results = qboInvoiceQuery.ExecuteQuery<Invoice>(_ServiceContext);
IEnumerable<Invoice> qboInvoices = results;
int iCount = results.Count();
while (iCount > 0 && iCount == iResultsPerPage && qboInvoiceQuery.PageNumber <= iMaxPageNumber)
qboInvoiceQuery.PageNumber++;
results = qboInvoiceQuery.ExecuteQuery<Invoice>(_ServiceContext);
iCount = results.Count();
qboInvoices = qboInvoices.Concat(results);
*** 更新 ***
我已经实现了 peterl 的答案,现在有以下代码。但是,我现在遇到了一个新问题,即我的代码总是返回 10 张发票的默认值,并且没有考虑到我的身体。即使我将其设置为不同的页码或ResultsPerPage 值,我也会得到第一页和10 个结果。有什么想法吗?
private Dictionary<string, Invoice> GetUnpaidInvoicesDictionary(IdType CustomerId, bool bById = true)
Dictionary<string, Invoice> dictionary = new Dictionary<string, Invoice>();
int iMaxPageNumber = 100;
int iResultsPerPage = 100;
try
OAuthConsumerContext consumerContext = new OAuthConsumerContext
ConsumerKey = _sConsumerKey,
SignatureMethod = SignatureMethod.HmacSha1,
ConsumerSecret = _sConsumerSecret
;
string sBaseURL = "https://oauth.intuit.com/oauth/v1";
string sUrlRequestToken = "/get_request_token";
string sUrlAccessToken = "/get_access_token";
OAuthSession oSession = new OAuthSession(consumerContext,
sBaseURL + sUrlRequestToken,
sBaseURL,
sBaseURL + sUrlAccessToken);
oSession.AccessToken = new TokenBase
Token = _sAccessToken,
ConsumerKey = _sConsumerKey,
TokenSecret = _sAccessTokenSecret
;
int iPageNumber = QUERY_START_PAGE_NUMBER;
string sCustomerId = CustomerId.Value;
string sBodyBase = "PageNum=0&ResultsPerPage=1&Filter=OpenBalance :GreaterThan: 0.00 :AND: CustomerId :EQUALS: 2";
string sBody = String.Format(sBodyBase, iPageNumber, iResultsPerPage, sCustomerId);
IConsumerRequest conReq = oSession.Request();
conReq = conReq.Post().WithRawContentType("application/x-www-form-urlencoded").WithRawContent(System.Text.Encoding.ASCII.GetBytes(sBody)); ;
conReq = conReq.ForUrl(_DataService.ServiceContext.BaseUrl + "invoices/v2/" + _DataService.ServiceContext.RealmId);
conReq = conReq.SignWithToken();
// Complete the Query calls to build the list
SearchResults searchResults = (SearchResults)_DataService.ServiceContext.Serializer.Deserialize<SearchResults>(conReq.ReadBody());
IEnumerable<Invoice> results = ((Invoices)searchResults.CdmCollections).Invoice;
IEnumerable<Invoice> qboInvoices = results;
int iCount = searchResults.Count;
while (iCount > 0 && iCount == iResultsPerPage && iPageNumber <= iMaxPageNumber)
iPageNumber++;
sBody = String.Format(sBodyBase, iPageNumber, iResultsPerPage, sCustomerId);
conReq = oSession.Request();
conReq = conReq.Post().WithRawContentType("application/x-www-form-urlencoded").WithRawContent(System.Text.Encoding.ASCII.GetBytes(sBody)); ;
conReq = conReq.ForUrl(_DataService.ServiceContext.BaseUrl + "invoices/v2/" + _DataService.ServiceContext.RealmId);
conReq = conReq.SignWithToken();
searchResults = (SearchResults)_DataService.ServiceContext.Serializer.Deserialize<SearchResults>(conReq.ReadBody());
results = ((Invoices)searchResults.CdmCollections).Invoice;
qboInvoices = qboInvoices.Concat(results);
iCount = searchResults.Count;
if (bById)
foreach (Invoice Inv in qboInvoices)
dictionary.Add(Inv.Id.Value, Inv);
else
foreach (Invoice Inv in qboInvoices)
dictionary.Add(Inv.Header.DocNumber, Inv);
return dictionary;
catch (Exception)
return null;
* 更新 *
有一个类似的问题涉及新的 api 测试器。这可能与此问题有关,他们目前正在调查。
Stack Overflow: QuickBooks Online querying with filter returns 401 everytime
【问题讨论】:
【参考方案1】:这是 DevKit 中的一个错误。 OpenBalance 过滤器默认为 :EQUALS: 并且不支持 :GreaterThan:。
https://ipp.developer.intuit.com/0010_Intuit_Partner_Platform/0050_Data_Services/0400_QuickBooks_Online/Invoice#Attributes_Supporting_Filtering_and_Sorting
这是使用 DevDefined 构造 OAuth 标头的解决方法:
public List<Intuit.Ipp.Data.Qbo.Invoice> GetQboUnpaidInvoices(DataServices dataServices, int startPage, int resultsPerPage, IdType CustomerId)
StringBuilder requestXML = new StringBuilder();
StringBuilder responseXML = new StringBuilder();
var requestBody = String.Format("PageNum=0&ResultsPerPage=1&Filter=OpenBalance :GreaterThan: 0.00 :AND: CustomerId :EQUALS: 2", startPage, resultsPerPage, CustomerId.Value);
HttpWebRequest httpWebRequest = WebRequest.Create(dataServices.ServiceContext.BaseUrl + "invoices/v2/" + dataServices.ServiceContext.RealmId) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.ContentType = "application/x-www-form-urlencoded";
httpWebRequest.Headers.Add("Authorization", GetDevDefinedOAuthHeader(httpWebRequest, requestBody));
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());
return ((Intuit.Ipp.Data.Qbo.Invoices)searchResults.CdmCollections).Invoice.ToList();
protected string GetDevDefinedOAuthHeader(HttpWebRequest webRequest, string requestBody)
OAuthConsumerContext consumerContext = new OAuthConsumerContext
ConsumerKey = consumerKey,
ConsumerSecret = consumerSecret,
SignatureMethod = SignatureMethod.HmacSha1,
UseHeaderForOAuthParameters = true
;
consumerContext.UseHeaderForOAuthParameters = true;
//URIs not used - we already have Oauth tokens
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")
Dictionary<string, string> formParameters = new Dictionary<string, string>();
foreach (string formParameter in requestBody.Split('&'))
formParameters.Add(formParameter.Split('=')[0], formParameter.Split('=')[1]);
consumerRequest = consumerRequest.WithFormParameters(formParameters);
consumerRequest = consumerRequest.SignWithToken();
return consumerRequest.Context.GenerateOAuthParametersForHeader();
http://nuget.org/packages/DevDefined.OAuth
【讨论】:
谢谢,您的代码确实有助于开始获得解决方案。我现在有意想不到的结果,没有考虑过滤、每页结果、页码等。如果您想试一试,我已经更新了我上面的问题。谢谢。 请尝试pastebin.com/raw.php?i=7VUB6whp 并确保您使用的是来自 NuGet 的最新版本的 DevDefined。您上面的代码(也许是我的原始示例)在请求正文中发送 OAuth 身份验证,没有任何其他字段,而不是标头。因此,该服务返回第 1 页的默认响应,其中包含 10 条记录。 我认为问题可能是上面示例代码中的 DevDefined 版本。我更新到最新了。 感谢您的回复。在我们完成构建之后,我将在今天晚些时候尝试这个。以上是关于使用 QuickBooks Online (QBO) Intuit 合作伙伴平台 (IPP) DevKit 查询所有未结余额发票的主要内容,如果未能解决你的问题,请参考以下文章
json QuickBooks Online v3 OpenAPI
json QuickBooks Online V3 API OpenAPI
Quickbooks Online沙盒返回等待激活,我有真正的Id,访问令牌