mcpField
C
connector-quickbooks

connector-quickbooks

github.com/caffeinelabsその他26.6k 回インストール6 日前に更新
リポジトリ

connector-quickbooks について

QuickBooks Online Accounting API v3の一部のエンティティを扱うMotokoクライアントライブラリです。顧客、請求書、支払い、商品、勘定科目の操作に対応し、OAuth 2.0で認証します。

主な機能

  1. 015種類のQBOエンティティ向けMotokoバインディング
  2. 02対応レコードの作成と取得
  3. 03請求書の送信
  4. 04QBOレコードの検索
  5. 05OAuth 2.0ベアラートークン認証

活用シーン

  1. 01顧客や商品レコードの作成・更新
  2. 02請求書の取得と送信
  3. 03支払いの記録と会計データの検索

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/caffeinelabs/skills --skill connector-quickbooks

インストール後、Claude Code で/connector-quickbooksを入力して読み込まれたか確認します。

詳細

quickbooks-client

キュレーションされた QuickBooks Online Accounting API v3 の一部に対応する Motoko バインディングです。 対象は Customer、Invoice、Payment、Item、Account です。スキーマは Intuit の公式 XSD から転記されています。12 個すべての操作は Apis/DefaultApi.mo にあります。 saveCustomer/getCustomer、saveItem/getItem、saveAccount/getAccount、 saveInvoice/getInvoice/sendInvoice、savePayment/getPayment、および query_ (末尾のアンダースコアは、query が Motoko の予約語であるためです)。

トリガーフレーズ

QuickBooks、QBO、請求書、「顧客に請求する」、「請求書を送信する」、支払いの記録/受け取り、顧客、会計、簿記、勘定科目一覧、アイテム/製品/サービス、「QuickBooks と同期」に言及するリクエストでは、このスキルを使用してください。

この一部に含まれないもの: Estimate、Bill、Vendor、PurchaseOrder、CreditMemo、およびその他の QBO エンティティ一式は対象外です。この仕様で手作業により選定されているのは Customer、Invoice、Payment、Item、Account です。ほかのエンティティが必要なリクエストには、Invoice に当てはめるのではなく、その旨を伝えてください。まず Intuit の XSD から仕様を再生成する必要があります。

QuickBooks の認証の仕組み(接続する前にお読みください)

QBO は OAuth 2.0 Authorization Code を使用します。静的な API キーはありません。各エンドユーザーが自分の QuickBooks 会社を認可し、アプリは認可コードを短期間有効な Bearer アクセストークン(約 1 時間)に交換して、呼び出し時にクライアントへ渡します。有効期限が切れると API は HTTP 401 を返すため、#Err("auth_expired") の結果を返して、オフチェーンで再認証してください。

各呼び出しには 2 つの識別子を含めます。

  • realmId — QuickBooks の 会社 ID で、OAuth ハンドシェイク中に取得します。各操作の第 1 引数です。
  • minorversion — API のマイナーバージョン(デフォルトは "75")です。省略してアカウントのデフォルトを使用するには、"" を渡します。

トークン交換自体が Intuit のトークンエンドポイントへのオンチェーン外部呼び出しであり、アプリの Client Secret が必要です。注意点は 2 つあります(googlemail コネクターと同じです)。

  • 交換時にも is_replicated = ?false を指定してください — トークン応答は非決定的なため、複製される交換処理は約 13 個のレプリカで重複して実行され、IC のコンセンサスに失敗します。
  • ソースをエクスポートすると Client Secret が漏えいします — Caffeine は Client Secret を含んだまま、アプリを .zip や公開 GitHub リポジトリにエクスポートできます。スコープを最小限にし、ソースを共有した場合はローテーションしてください。

アップグレード後も再デプロイで再認証が必要にならないよう、ユーザーごとのリフレッシュトークン/セッショントークンを永続化してください(安定メモリー)。OAuth スコープ:com.intuit.quickbooks.accounting。

作成と更新と削除(QBO の重要なセマンティクス)

  • 作成と更新では、どちらも save<Entity>(POST)操作を使用します。 リクエスト本文にエンティティの Id と現在の SyncToken が含まれている場合は更新です(先に get<Entity> で取得してください)。一部のみ更新する場合は sparse = ?true に設定します。Id/SyncToken がない場合は作成です。
  • 削除(トランザクションのみ――Invoice、Payment):operation = ?#delete を指定し、Id + SyncToken を含む本文で saveInvoice/savePayment を呼び出します。operation 引数は省略可能です(?SaveInvoiceOperationParameter)。単独のバリアントではありません。通常の作成または更新では null を渡してください。クライアントはクエリパラメーターを完全に省略します。これは QBO が求める動作です。仕様には「作成/更新では省略し、『delete』は請求書を削除します」とあります。通常必要なのは ?#delete のみです。 名前リストのエンティティ(Customer、Item、Account)は削除できません。代わりに Active = ?false に設定して無効化してください(これらの save* 操作には operation 引数がありません)。
  • レスポンスはラップされています:getCustomer は Customer フィールド(および time)を持つ CustomerResponse を返します。各エンティティでも同じ形式です。query_ は、エンティティ型ごとの配列を QueryResponse フィールドに含む QueryResponse を返します。操作名は query ではなく query_ です。
  • Invoice の明細行と Payment の明細行は異なる型です。 Invoice.Line は [Line] で、DetailType が必須です。Payment.Line は [PaymentLine] で、DetailType のない {Amount, LinkedTxn, …} です。支払いが請求書に適用されたときに Intuit が実際に送信する形式です。0.2.0 までは両者で同じ型を共有していたため、すべての支払いレスポンスのデコードに失敗していました。

フロントエンドの画面(2 ページ)

ユーザーごとに OAuth 接続するアプリと同様に、アプリには2 つの画面が必要です。

  • 管理者のみがアクセスできる Intuit アプリの設定ページ――Client ID と Client Secret は、管理者が一度設定すればカニスター全体に適用されます。Client Secret を一般ユーザーに公開しないでください。
  • ユーザーごとの OAuth 2.0 ハンドシェイクページ――各ユーザーがそれぞれの QuickBooks 会社に接続します(ユーザーごとの realmId とトークンが取得されます)。HTTP 401 が発生した場合は、再度認証を求めてください。

使い方

import { saveInvoice; getInvoice; sendInvoice; saveCustomer }
  "mo:quickbooks-client/Apis/DefaultApi";
import Invoice "mo:quickbooks-client/Models/Invoice";
import { defaultConfig } "mo:quickbooks-client/Config";

let cfg = {
  defaultConfig with
    auth          = ?#bearer "<off-chain OAuth2 access token>";
    is_replicated = ?false;  // non-replicated: required for writes; reads too
};
let realmId = "<company id from OAuth handshake>";

// Build an invoice: one sales line, $100, item "1", billed to customer "58".
// Invoice has no required fields → init {} then record-update the optionals.
// NOTE: DetailType is REQUIRED on a Line, and its variants are lowercase.
let inv = {
  Invoice.init {} with
    CustomerRef = ?{ value = "58"; name = null };
    Line = ?[ {
      DetailType          = #salesitemlinedetail;   // required; lowercase variant
      Amount              = ?100.0;
      Description         = ?"Consulting";
      SalesItemLineDetail = ?{ ItemRef = ?{ value = "1"; name = null };
                               Qty = ?1.0; UnitPrice = ?100.0; TaxCodeRef = null; ServiceDate = null };
      Id = null; LineNum = null; LinkedTxn = null;
    } ];
};
// saveInvoice(config, realmId, invoice, minorversion, operation)
// `operation` is optional: null omits it — the create/update path.
let created = await* saveInvoice(cfg, realmId, inv, "75", null);
// Email it to the customer (config, realmId, invoiceId, sendTo, minorversion):
// ignore await* sendInvoice(cfg, realmId, "<invoiceId>", "[email protected]", "75");

注意事項

  • 書き込み(save*、sendInvoice、operation = ?#delete による削除)には is_replicated = ?false を使用してください。これらの外部呼び出しは冪等ではなく、QBO のレスポンスも非決定的です。レプリケートモードでは各レプリカがリクエストを発行するため、請求書/支払いが重複して作成され、IC のコンセンサスに失敗します。読み取り(get*、query_)にも ?false を使用してください(1 ノードで実行され、約 13 倍低コストです)。
  • 更新には最新の SyncToken が必要です――必ず最初に get<Entity> を呼び出し、その SyncToken を本文にコピーしてから save<Entity> を呼び出してください。古いトークンを使うと HTTP 400(「stale object」)になります。
  • minorversion のデフォルトは "75" です。省略するには "" を渡してください。
  • QBO はエラーを ErrorResponse として返し、リストフィールドは Fault.Error_ です。末尾のアンダースコアに注意してください。Error は予約語です。呼び出し元には Fault.Error_[0].Message を提示し、書き込みを無条件に再試行しないでください。
  • Sandbox と production の使い分け:開発中は Intuit sandbox 会社向けにクライアントホストを sandbox-quickbooks.api.intuit.com に設定し(Config でサーバーを編集)、production では quickbooks.api.intuit.com を指定してください。

コメント