@apigrate/快书
透明 单站 用于与快书在线API互动的库。 它支持您需要与快书在线会计API互动的所有功能,包括:
- 自动 OAuth2 令牌刷新(包括事件处理器)
- 支持本土承诺
- 未显示的错误处理
- 构造器 OAuth URL 的方便方法
- 最重要的是, quickBooks 在线会计 API 的完整覆盖。 。 。 .
版本4.x 变动
现在使用Intuit发现文档,动态地从Intuit OAuth上加载正确的URL.
变化 :
- 已添加
is_sandbox布尔到构造器。 使用此选项来指定沙盒 vs 生产环境 . - 已添加
intuit_tid将返回accountingApi()。这个包含最后一个 API 调用intuit_tid值,用于开发者支持排除出错. intuit_tid属性添加到 ApiErrors 和 ApiThrotlingErrors .- 为某些实体增加了虚拟支持。 你可以使用一个
.voidTransaction()发票、账单、付款和销售交易业务
中断更改 :
getIntuitAuthorizationUrl函数现在是连接器实例上的一种同步方法.
支助的实体
支持的交易实体:
| 实体 | 查询 | 创建 | 由 id 获取 | 更新 | 删除 | 无效 |
|---|---|---|---|---|---|---|
| 比尔 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 账单付款 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 信用备忘录 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 交存 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 估计数 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 发票 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 日记条目 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 付款 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 采购 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 定购单 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 退款收回 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 销售检索 | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ |
| 时间活性 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 转让 | ✓ | ✓ | ✓ | ✓ | ✓ | |
| 供应商编辑 | ✓ | ✓ | ✓ | ✓ | ✓ |
已命名的列表实体 :
| 实体 | 参考文献 | 查询 | 创建 | 由 id 获取 | 更新 | 删除 |
|---|---|---|---|---|---|---|
| 账户 | 账户 | ✓ | ✓ | ✓ | ✓ | |
| 预算 | 预算 | ✓ | ✓ | |||
| 类 | 类 | ✓ | ✓ | ✓ | ✓ | |
| 公司数量 | 公司货币 | ✓ | ✓ | ✓ | ✓ | |
| 客户 | 客户 | ✓ | ✓ | ✓ | ✓ | |
| 部门 | 部门 | ✓ | ✓ | ✓ | ✓ | |
| 雇员 | 雇员 | ✓ | ✓ | ✓ | ✓ | |
| 项目 | 项目 | ✓ | ✓ | ✓ | ✓ | |
| 日记码 | 日记代码 | ✓ | ✓ | ✓ | ✓ | |
| 支付方法 | 付款方法 | ✓ | ✓ | ✓ | ✓ | |
| 税务机构 | 税务机构 | ✓ | ✓ | ✓ | ||
| 税则 | 税码 | ✓ | ✓ | ✓ | ||
| 税收 | 税率 | ✓ | ✓ | ✓ | ||
| 税务服务 | 税务/税法 | ✓ | ✓ | |||
| 任期 | 任期 | ✓ | ✓ | ✓ | ✓ | |
| 供应商 | 供应商 | ✓ | ✓ | ✓ | ✓ |
支助实体:
| 实体 | 参考文献 | 查询 | 创建 | 由 id 获取 | 更新 | 删除 |
|---|---|---|---|---|---|---|
| 可附加 | 可附加 | ✓ | ✓ | ✓ | ✓ | ✓ |
| 公司信息 | 公司信息 | ✓ | ✓ | ✓ | ||
| 首选项 | 偏好 | ✓ | ✓ | ✓ |
报告:
| 报告 |
|---|
| 账户列表详细报告 |
| APAGING 详细报告 |
| APAGING 简要报告 |
| 详细报告 |
| ARAGING 简要报告 |
| 平衡面板报告 |
| 现金 |
| 客户报告 |
| 客户详细报告 |
| 客户收入报告 |
| 一般编辑报告 |
| 通用编目报告FR |
| 库存估价 摘要报告 |
| 《日刊》报告 |
| 利润和损失报告 |
| 利润和损失详细报告 |
| 销售分类摘要报告 |
| 销售情况报告 |
| 销售部报告 |
| 销售产品报告 |
| 税务简要报告 |
| 交易列表报告 |
| 审判报告FR |
| 审判报告 |
| 供应商报告 |
| 供应商详细报告 |
| 供应商支出报告 |
使用量
let {QboConnector} = require('@apigrate/quickbooks');
let connector = new QboConnector(
client_id,
client_secret,
redirect_uri,
access_token,
refresh_token,
realm_id,
minorversion
);
//Get the accounting API object.
let qbo = await connector.accountingApi();
//Now you can make API calls!
构造器选项 :
- 客户端( d) (单位:千美元)字符串,要求) 因图伊特为您的应用程序指定客户端ID.
- 客户端 机密 (单位:千美元)字符串,要求) Intuit为您的应用程序指定了客户端秘密.
- 方向调整 uri (单位:千美元)字符串, 需要) 用于您的应用程序的有效注册重定向 URI 。 注意,对于生产,这必须是SSL链接(HTTPS).
- 访问( t) (单位:千美元)字符串,有条件的) 熊克令牌,用于API调用授权头. 你应该从自己的仓库里拿到这个.
- 刷新( tk) (单位:千美元)字符串,有条件) 切换到过期时刷新 access token 。 你应该从自己的仓库里拿到这个.
- 域名( d) 编号 (单位:千美元)字符串,有条件的)Intuit公司标识,用于API调用URL. 你应该从自己的仓库里拿到这个.
- 证书 初始化器 (单位:千美元)函数,有条件) 初始化的同步函数
access_token, (中文(简体) ),refresh_token,以及realm_id;它被设计为bbe用来代替提供它们作为构造参数. 您执行的函数必须返回表单的证书对象 :{ access_token, refresh_token, realm_id}。在第一个API方法引用时自动引用此函数。 如果您省略了此功能, 您需要调用setCredentials方法,在您第一次 API 方法引用之前使用同一结构的对象. - 微调 (单位:千美元)编号,可选)指定每个API呼叫上要传递的QuickBooks API小版本参数
- 转向后退 (单位:千美元)编号,可选),在收到HTTP 429(速率限制)响应后,等待重试请求的毫秒数. 默认为
10000(10秒钟). 见 处理错误 更多细节. - 基数Url (单位:千美元)字符串,有条件) API呼叫的Intuit基础URL. 未提供时, 它默认为 API 的 Intuit 生产基础 URL :
https://quickbooks.api.intuit.com/v3然而对于快书沙盒的使用, 您必须明确提供数字 :https://sandbox-quickbooks.api.intuit.com/v3
连接器会自动使用任何提供的证书来更新过期的 access token 。 连接器发出 a token.refreshed 内部事件,当它这样做。 执行您自己的收听器功能来存储证书 .
//Event hook to handle a token refresh.
connector.on('token.refreshed', function(credentials){
console.log('Token was refreshed.');
//Use this function to store/update your OAuth data
//The credentials object may have the following properties:
credentials.access_token; //Bearer token for API calls.
credentials.expires_in; //how long before access token expires, in s
credentials.refresh_token; //for getting another access token
credentials.x_refresh_token_expires_in; //how long before refresh_token expires, in s
credentials.realm_id; //the qbo company id
});
制作API电话
您使用从 QD 中返回的对象进行 QuickBooks 会计 API 调用 connector.accountingApi() 方法(以下简称示例) qbo) (中文(简体) ). 此实体将 快书在线会计API。 。 。 .
查询
使用 Intuit 查询语法查询任意类型的对象 .
实体.query(报表,选择)
statement(单位:千美元)字符串查询语句(参见数据查询用于您正在合作的实体opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
let result = await qbo.Item.query(
`select * from Item where Active=true and Type='Inventory'`
);
这个 result 为:
{
"QueryResponse": {
"Item": [
{
"Name": "Pump",
"Description": "Fountain Pump",
"Active": true,
"FullyQualifiedName": "Pump",
"Taxable": true,
"UnitPrice": 15,
"Type": "Inventory",
"IncomeAccountRef": {
"value": "79",
"name": "Sales of Product Income"
},
"PurchaseDesc": "Fountain Pump",
"PurchaseCost": 10,
"ExpenseAccountRef": {
"value": "80",
"name": "Cost of Goods Sold"
},
"AssetAccountRef": {
"value": "81",
"name": "Inventory Asset"
},
"TrackQtyOnHand": true,
"QtyOnHand": 25,
"InvStartDate": "2018-03-29",
"domain": "QBO",
"sparse": false,
"Id": "11",
"SyncToken": "3",
"MetaData": {
"CreateTime": "2018-03-26T10:46:45-07:00",
"LastUpdatedTime": "2018-03-29T13:16:17-07:00"
}
}
]
}
}
注意,虽然Intuit查询API端点对所有实体都是通用的,但如果在适当的实体端点上使用查询方法,连接器会提供一些额外的保障验证. 例如,我们建议使用
qbo.Items.query改为qbo.query以明确代码.
获取身份
你需要的只是实体身份,你可以找到实体的全部细节.
实体. get( id, 选项)
id(单位:千美元)编号用于您想要获取的实体的 idopts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
示例:获取项目:
let result = await qbo.Item.get(11);
这个 result 为:
{
"Item": {
"Name": "Widget",
"Active": true,
"FullyQualifiedName": "Widget",
"Taxable": false,
"UnitPrice": 0,
"Type": "Service",
"IncomeAccountRef": {
"value": "79",
"name": "Sales of Product Income"
},
"PurchaseCost": 0,
"TrackQtyOnHand": false,
"domain": "QBO",
"sparse": false,
"Id": "21",
"SyncToken": "0",
"MetaData": {
"CreateTime": "2018-11-13T14:41:34-08:00",
"LastUpdatedTime": "2018-11-13T14:41:34-08:00"
}
},
"time": "2018-11-13T15:08:40.458-08:00"
}
创建
这个 .create() 方法用于创建实体。 记住,根据您创建的实体类型,可以有条件地要求一些字段.
实体. 创建( 负载, 选择)
payload(单位:千美元)对象) 包含要创建的物体的所有可写入字段的物体有效载荷.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
示例: 创建项目
let result = await qbo.Item.create({
"Name": 'Widget',
"Type": 'Inventory',
"IncomeAccountRef": {
"value": "79",
"name": "Sales of Product Income"
}
});
这个 result 为:
{
"Item": {
"Name": "Widget",
"Active": true,
"FullyQualifiedName": "Widget",
"Taxable": false,
"UnitPrice": 0,
"Type": "Service",
"IncomeAccountRef": {
"value": "79",
"name": "Sales of Product Income"
},
"PurchaseCost": 0,
"TrackQtyOnHand": false,
"domain": "QBO",
"sparse": false,
"Id": "21",
"SyncToken": "0",
"MetaData": {
"CreateTime": "2018-11-13T14:41:34-08:00",
"LastUpdatedTime": "2018-11-13T14:41:34-08:00"
}
},
"time": "2018-11-13T14:41:34.885-08:00"
}
示例:创建比尔
let result = await qbo.Bill.create({
"Line": [
{
"DetailType": "AccountBasedExpenseLineDetail",
"Amount": 200.0,
"Id": "1",
"AccountBasedExpenseLineDetail": {
"AccountRef": {
"value": "7"
}
}
}
],
"VendorRef": {
"value": "42"
}
});
这个 result 为:
{
"Bill": {
"DueDate": "2020-08-25",
"Balance": 200,
"domain": "QBO",
"sparse": false,
"Id": "145",
"SyncToken": "0",
"MetaData": {
"CreateTime": "2020-08-25T06:27:05-07:00",
"LastUpdatedTime": "2020-08-25T06:27:05-07:00"
},
"TxnDate": "2020-08-25",
"CurrencyRef": {
"value": "USD",
"name": "United States Dollar"
},
"Line": [
{
"Id": "1",
"LineNum": 1,
"Amount": 200,
"LinkedTxn": [],
"DetailType": "AccountBasedExpenseLineDetail",
"AccountBasedExpenseLineDetail": {
"AccountRef": {
"value": "7",
"name": "Advertising"
},
"BillableStatus": "NotBillable",
"TaxCodeRef": {
"value": "NON"
}
}
}
],
"VendorRef": {
"value": "42",
"name": "Lee Advertising"
},
"APAccountRef": {
"value": "33",
"name": "Accounts Payable (A/P)"
},
"TotalAmt": 200
},
"time": "2020-08-25T06:27:05.412-07:00"
}
更新
和 .update() 用于更新 API 实体的方法。 在更新实体时,大多数实体支持一个"完整更新"模式,在此模式中,预计您会发送整个一组要更新的字段(任何缺失都会被设定为无效). 因此,建议你:
- 先把完整的实体拿来,
- 修改要更改的字段,
- 将完整对象送回,作为更新操作的一部分.
见 退出快书在线 API 文档 以了解更多关于您与之合作的实体的详细信息.
实体.update(载荷,选择)
payload(单位:千美元)对象) 包含要更新的物体所有可写入字段的物体有效载荷.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
示例:更新项目
let existing = await qbo.Item.get(19);
existing.Item.Name="Rubber Ducky";
let result = await qbo.Item.update(existing.Item);
这个 result 为:
{
"Item": {
"Name": "Rubber Ducky",
"Active": true,
"FullyQualifiedName": "Rubber Ducky",
"Taxable": false,
"UnitPrice": 0,
"Type": "Service",
"IncomeAccountRef": {
"value": "79",
"name": "Sales of Product Income"
},
"PurchaseCost": 0,
"TrackQtyOnHand": false,
"domain": "QBO",
"sparse": false,
"Id": "21",
"SyncToken": "1",
"MetaData": {
"CreateTime": "2018-11-13T14:41:34-08:00",
"LastUpdatedTime": "2019-08-28T12:05:02-08:00"
}
},
"time": "2019-08-28T12:05:02.148-08:00"
}
删除
大多数交易实体都支持删除,但只有少数命名列表实体支持. 在删除时,你需要两个 Id 编辑 SyncToken类似 update() 方法,通常最好在删除之前立即取出一个实体,以获取最新的 SyncToken。 。 。 .
你可以考虑
SyncToken作为你与之合作的实体的"版本号". 它是一种防止两个人同时对同一个实体进行修改的机制.
实体. delete( 载荷, 选择)
payload(单位:千美元)对象(b) 载有下列两种物体的有效载荷:Id编辑SyncToken对象的属性.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
示例:删除法案
let result = await qbo.Bill.delete({
"Id": 145,
"SyncToken": 0
});
这个 result 为:
{
"Bill": {
"domain": "QBO",
"status": "Deleted",
"Id": "145"
},
"time": "2020-08-25T06:48:57.291-07:00"
}
对于不支持"硬删除"的entites,通常有通过设置来"软删除"的方法
Active=false使用update()方法,或者类似的东西.
虚拟
某些因图伊特实体(BillPayment、发票、付款、销售回购)支持Void。 这些与更新类似, 但您必须使用 .voidTransaction() 执行空隙的方法.
实体.void 交易(载荷,选择)
payload(单位:千美元)对象含有物体空有效载荷场的物体有效载荷。 通常你需要提供有效载荷,例如:{Id: 192, SyncToken: 0}。注意,这意味着您应该先取回实体,然后将其撤销,因为您应该使用当前实体的同步符号.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
批量请求
批量请求( 包含一个请求的多个操作) 已支持 ! 这里有一个代码示例。 这将删除多个时间活动, 但您可以混合您自己的交易类型 。 它们不需要是同一类实体或行动.
实体.batch( 有效载荷, 选择)
payload(单位:千美元)对象载有批量请求的物体有效载荷。 (见 因纽特文档 关于如何进行批量操作的详情.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
try{
let activities = [
{Id: 123489, SyncToken: 0},
{Id: 178275, SyncToken: 0},
{Id: 189085, SyncToken: 0},
///...
{Id: 190239, SyncToken: 0},
];//Only Id and SyncToken are needed on each for delete
let batch = {
BatchItemRequest: []
}
for(let i=0; i<activities.length; i++){
let activityToDelete = activities[i];
batch.BatchItemRequest.push({
bId: i,
operation: "delete",
TimeActivity: {
Id: activityToDelete.Id,
SyncToken: activityToDelete.SyncToken
}
});
}
//Invoke Batch API
await qbo.batch(batch);
} catch (err) {
//...
}
请注意,由于您可以在批量请求中混合实体的类型,所以这种方法不会在实体上命名空格(它直接存在于 qbo 对象).
运行报表
只需使用 query 对每个报告实体采用方法,作为散列提供参数.
报告实体.query(武器,选择)
parms(单位:千美元)对象一个其属性将作为报告请求参数的对象.opts(单位:千美元)对象,可选)reqid(单位:千美元)字符串,可选) 独有的请求ID,因图伊特在出错时使用"重放"交易. 发送请求身份证明并不必要,但被认为是最佳做法.minor_version(单位:千美元)编号,可选),用于请求的API特定次要版本. 覆盖minor_version构造参数,如果提供了.
示例:运行客户收入报告
let result = await qbo.CustomerIncomeReport.query(
{
start_date: '2019-01-01',
end_date: '2020-04-01'
}
);
这个 result 为:
{
"Header": {
"Time": "2020-08-21T15:04:49-07:00",
"ReportName": "CustomerIncome",
"ReportBasis": "Accrual",
"StartPeriod": "2019-01-01",
"EndPeriod": "2020-04-01",
"Currency": "USD",
"Option": [
{
"Name": "NoReportData",
"Value": "false"
}
]
},
"Columns": {
...etc
},
"Rows": {
...etc
}
}
(为长度删除了一些细节)
处理错误
API 特定错误( 通常为 HTTP-4xx) 响应, 被困入并被扔入 ApiError 课。 下列错误类别可供使用:
- 痛苦 - API一般错误(HTTP 4xx/5xx答复)
- Apithrottling (英语) 错误 - 亚类
ApiError,当HTTP 429在尝试用尽后遇到回复时抛出 - 证书错误 - OAuth 证书缺失或无效时丢弃
- Token Refresh 错误 - 当访问令牌刷新失败时丢弃
自动刷新
当API呼叫收到HTTP 401(未经授权)响应后,连接器会自动尝试使用刷新符刷新访问令牌并重试请求一次. 如果刷新成功的话 token.refreshed 事件被发布(参见 使用量 如何处理此事件)。 如果刷新失败, a TokenRefreshError 被抛出.
自动转动后退
当API呼叫收到HTTP 429(太多请求)响应后,连接器会自动等待并重复请求一次. 等待时间可通过 throttle_backoff 构造器选项( 默认值: 10秒 / 1000ms) .
let connector = new QboConnector({
client_id: 'your_client_id',
client_secret: 'your_client_secret',
redirect_uri: 'your_redirect_uri',
throttle_backoff: 60000
});
如果重试还收到HTTP 429回复,则 ApiThrottlingError 被抛出.
示例: 试图创建失败的字段
const {ApiError} = require('@apigrate/quickbooks');
try{
let result = qbo.Item.create({
"Name": "Body Armor",
"Type": "Inventory"
//This will fail because there are other fields required...
});
} catch (err){
if(err instanceof ApiError){
err.message; //contains a readable, parsed error message,
err.payload; //the object payload of the error, if one was returned
}
}
err.payload 示例:
{
"Fault": {
"Error": [
{
"Message": "Object Not Found",
"Detail": "Object Not Found : Something you're trying to use has been made inactive. Check the fields with accounts, customers, items, vendors or employees.",
"code": "610",
"element": ""
}
],
"type": "ValidationFault"
},
"time": "2018-11-13T15:21:29.433-08:00"
}
请注意:
Fault.Error是一个 数组,虽然大多数时候只有一个错误。 对于每个错误Message是该错误的高级解释.
OAuth 获得 IntuitAuthorization Url = 函数(状态)
连接器还为构建一个 客户端对因地制宜 启动用户 OAuth2 授权程序的 URL.
参数:
- 状态 (字符串) 提供任何可能对您收到答复后的申请有用的状态. Intuit 授权服务器绕行此参数, 因此您的应用程序收到它发送的值 。 建议在州内设置一个CSRF标志.
返回所有参数设置和编码的授权 URL 字符串. 你用这个来做你自己的电话, 典型的UI组件. 注意,当用户认证后重定向 uri被引用时,将包含以下查询参数:
code(这是你们用来交换访问符和刷新符)realmId- 这代表QBO公司 普因图伊特的指示应该安全地储存起来.