定制 shukyusof/qb-sdk 二次开发

按需修改功能、优化性能、对接业务系统,提供一站式技术支持

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

shukyusof/qb-sdk

Composer 安装命令:

composer require shukyusof/qb-sdk

包简介

Laravel SDK for QuickBooks Online (QBO) — OAuth2, multi-company, multi-tenant

README 文档

README

A Laravel-first Composer SDK for QuickBooks Online (QBO). Supports single-company apps, multi-company setups, and full SaaS multi-tenant platforms from the same codebase — with driver-based token storage, flexible company resolution, and automatic OAuth2 token refresh.

Requirements

Version
PHP 8.1+
Laravel 10.x / 11.x / 12.x

Installation

composer require shukyusof/qb-sdk

Laravel auto-discovers the service provider. To publish the config and migrations:

php artisan vendor:publish --tag=quickbooks-config
php artisan vendor:publish --tag=quickbooks-migrations
php artisan vendor:publish --tag=quickbooks-stubs
php artisan migrate

Configuration

Add these to your .env:

QUICKBOOKS_CLIENT_ID=your_client_id
QUICKBOOKS_CLIENT_SECRET=your_client_secret
QUICKBOOKS_REDIRECT_URI=https://yourapp.com/quickbooks/callback
QUICKBOOKS_ENVIRONMENT=production          # or sandbox
QUICKBOOKS_TOKEN_STORE=database            # or cache
QUICKBOOKS_COMPANY_RESOLVER=model          # env | model | static | chain

# Single-company shorthand
QUICKBOOKS_DEFAULT_COMPANY=your-qb-company-uuid

# Optional tuning
QUICKBOOKS_TIMEOUT=30
QUICKBOOKS_RETRY_TIMES=3
QUICKBOOKS_RETRY_SLEEP=1000

Quickstart

1. Register a company source (one-time)

use App\Models\QuickBooksCompany;

$company = QuickBooksCompany::registerSource($yourModel, tenantId: null, labelColumn: 'name');
// $company->qb_company_id  →  UUID used everywhere in the SDK

2. Redirect the user to QuickBooks to authorize

use QuickBooks\SDK\Laravel\Facades\QuickBooks;

$url = QuickBooks::getAuthorizationUrl($company->qb_company_id);
return redirect($url);

3. Handle the OAuth callback

public function callback(Request $request)
{
    $client = QuickBooks::handleCallback(
        $request->get('code'),
        $request->get('realmId'),
        $request->get('state')
    );

    // $client is ready to use immediately
}

4. Use the client

$client = QuickBooks::company($qbCompanyId);

// or for single-company apps:
$client = QuickBooks::client();

Available Resources

All resources inherit all(), find($id), create($payload), update($payload), sparseUpdate($payload), and query($sql) from BaseResource.

Invoices

$client->invoices()->all();
$client->invoices()->find('123');
$client->invoices()->overdue();             // Balance > 0
$client->invoices()->create([...]);
$client->invoices()->sparseUpdate(['Id' => '1', 'SyncToken' => '0', 'PrivateNote' => 'x']);

Customers

$client->customers()->all();
$client->customers()->active();
$client->customers()->findByEmail('user@example.com');
$client->customers()->create([...]);

Payments

$client->payments()->all();
$client->payments()->find('456');
$client->payments()->create([...]);

Accounts (Chart of Accounts)

$client->accounts()->all();
$client->accounts()->getByType('Expense');
// Valid types: Bank, Other Current Asset, Fixed Asset, Other Asset,
//   Accounts Receivable, Equity, Expense, Other Expense,
//   Cost of Goods Sold, Accounts Payable, Credit Card,
//   Long Term Liability, Other Current Liability, Income, Other Income

Vendors

$client->vendors()->all();
$client->vendors()->active();
$client->vendors()->findByName('Acme Supplies');
$client->vendors()->create([...]);

Bills (Accounts Payable)

$client->bills()->all();
$client->bills()->unpaid();                 // Balance > 0
$client->bills()->forVendor($vendorId);
$client->bills()->create([...]);

Purchase Orders

$client->purchaseOrders()->all();
$client->purchaseOrders()->open();          // POStatus = 'Open'
$client->purchaseOrders()->forVendor($vendorId);
$client->purchaseOrders()->create([...]);

Estimates

$client->estimates()->all();
$client->estimates()->pending();            // TxnStatus = 'Pending'
$client->estimates()->accepted();           // TxnStatus = 'Accepted'
$client->estimates()->forCustomer($customerId);
$client->estimates()->create([...]);

Credit Memos

$client->creditMemos()->all();
$client->creditMemos()->unapplied();        // Balance > 0
$client->creditMemos()->forCustomer($customerId);
$client->creditMemos()->create([...]);

Employees

$client->employees()->all();
$client->employees()->active();
$client->employees()->findByName('Jane Smith');
$client->employees()->create([...]);

Calling Resources Not Covered by a Typed Class

The SDK ships typed classes for the most commonly used QBO entities. For everything else — JournalEntry, TaxRate, TaxCode, CompanyInfo, Department, Class, Item, RefundReceipt, SalesReceipt, Transfer, Deposit, and any other QBO entity — use the raw client methods directly.

get($uri, $query = [])

// Fetch a single record
$client->get('taxrate/1');
$client->get('item/42');
$client->get('department/5');

// Fetch with query parameters
$client->get('companyinfo/' . $realmId);

post($uri, $payload = [])

// Create any entity
$client->post('journalentry', [
    'Line' => [...],
    'CurrencyRef' => ['value' => 'USD'],
]);

// Create a sales receipt
$client->post('salesreceipt', [
    'CustomerRef' => ['value' => '1'],
    'Line' => [...],
]);

query($sql)

QBO supports a SQL-like query language across all entities. Use this for any entity that supports querying:

// Journal entries
$client->query("SELECT * FROM JournalEntry WHERE DocNumber = 'JE-001'");

// Tax rates
$client->query("SELECT * FROM TaxRate WHERE Active = true");

// Items / products
$client->query("SELECT * FROM Item WHERE Type = 'Inventory'");
$client->query("SELECT * FROM Item WHERE Name LIKE '%Widget%'");

// Company info
$client->query("SELECT * FROM CompanyInfo");

// Departments
$client->query("SELECT * FROM Department WHERE Active = true");

// Classes
$client->query("SELECT * FROM Class WHERE Active = true");

// Deposits
$client->query("SELECT * FROM Deposit WHERE TotalAmt > '1000'");

// Sales receipts
$client->query("SELECT * FROM SalesReceipt WHERE Balance > '0'");

// Refund receipts
$client->query("SELECT * FROM RefundReceipt");

// Transfers
$client->query("SELECT * FROM Transfer");

// Time activities
$client->query("SELECT * FROM TimeActivity WHERE BillableStatus = 'Billable'");

Note: String values in QBO query language must be wrapped in single quotes. Numeric comparisons do not require quotes.

Exception Handling

use QuickBooks\SDK\Exceptions\AuthenticationException;
use QuickBooks\SDK\Exceptions\RateLimitException;
use QuickBooks\SDK\Exceptions\ApiException;
use QuickBooks\SDK\Exceptions\CompanyNotFoundException;
use QuickBooks\SDK\Exceptions\QuickBooksException;

try {
    $invoices = QuickBooks::company($id)->invoices()->all();
} catch (RateLimitException $e) {
    // HTTP 429 — back off and retry later
} catch (AuthenticationException $e) {
    // OAuth expired or invalid — re-authorize the company
} catch (CompanyNotFoundException $e) {
    // Unknown qb_company_id
} catch (ApiException $e) {
    // Other HTTP error (404, 500, etc.)
    // $e->getCode() returns the HTTP status code
} catch (QuickBooksException $e) {
    // Catch-all for any SDK exception
}

Multi-Company

// Check connection state
QuickBooks::isConnected($qbCompanyId);   // bool
QuickBooks::connectionStatus();           // ['uuid' => bool, ...]

// Iterate all connected companies
foreach (QuickBooks::allCompanies() as $qbCompanyId => $client) {
    $client->invoices()->overdue();
}

// Disconnect
QuickBooks::disconnectCompany($qbCompanyId);

Multi-Tenancy

Set the tenant context before resolving a client — typically in middleware:

use QuickBooks\SDK\Tenant\TenantContext;

app(TenantContext::class)->setTenantId($request->user()->tenant_id);

Then use the SDK normally. All token reads and writes are automatically scoped to the active tenant.

Token Storage Drivers

Driver Config Use case
database QUICKBOOKS_TOKEN_STORE=database Default, persistent
cache QUICKBOOKS_TOKEN_STORE=cache Redis/Memcached, TTL-aware
tenant_database QUICKBOOKS_TOKEN_STORE=tenant_database Multi-tenant DB isolation

Company Resolver Drivers

Driver Config Use case
model QUICKBOOKS_COMPANY_RESOLVER=model Reads from quickbooks_companies table
env QUICKBOOKS_COMPANY_RESOLVER=env Comma-separated UUIDs in QUICKBOOKS_COMPANIES
static QUICKBOOKS_COMPANY_RESOLVER=static Hardcoded array, useful for testing
chain QUICKBOOKS_COMPANY_RESOLVER=chain Merges multiple resolvers with deduplication

Artisan Commands

# Register all records from a model as QBO companies
php artisan qb:register "App\Models\Company" --label=name

# With tenant scoping
php artisan qb:register "App\Models\Company" --label=name --tenant=tenant-uuid

# With a where-filter
php artisan qb:register "App\Models\Company" --label=name --filter="is_active=1"

License

MIT

shukyusof/qb-sdk 适用场景与选型建议

shukyusof/qb-sdk 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 8 次下载、GitHub Stars 达 0, 最近一次更新时间为 2026 年 02 月 20 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「oauth2」 「laravel」 「Accounting」 「quickbooks」 「intuit」 「qbo」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 shukyusof/qb-sdk 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 shukyusof/qb-sdk 我们能提供哪些服务?
定制开发 / 二次开发

基于 shukyusof/qb-sdk 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 8
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 0
  • 点击次数: 23
  • 依赖项目数: 0
  • 推荐数: 0

GitHub 信息

  • Stars: 0
  • Watchers: 0
  • Forks: 0
  • 开发语言: PHP

其他信息

  • 授权协议: MIT
  • 更新时间: 2026-02-20