Bannerify
記事一覧

PHP で JSON から請求書 PDF を動的に生成する

請求書は 1 度デザインして、請求データから 1 通ずつ生成します。JSON から作る表、QR 決済コード、ホスト済み PDF のリンクを、PHP のコード例で紹介します。

· Duc An

請求書は、どのプロダクトもいずれ生成することになる書類で、しかも作るのがいちばん面白くない書類です。Dompdf や TCPDF では、レイアウトを HTML と CSS で表現することになり、それが半分しかうまくいきません。FPDF は座標を指定して文字を置く方式です。表が 1 つあるだけのページのために、ヘッドレス Chrome のワーカーを用意するのは、インフラとして大げさです。

難しいのはレイアウトではありません。請求書の見た目は毎回同じです。変わるのはデータです。宛先、明細、合計、税率です。

そこで、ここで紹介する方法は次のとおりです。請求書を 1 度デザインしてテンプレートとして保存し、請求データを JSON で PDF 生成 API に送ります。API は、完成した PDF を返します。

必要なもの

  • ロゴ、住所のブロック、明細の表、合計のブロック、フッターを入れたテンプレート。エディターで作り、各レイヤーに名前を付けます。レイヤーを指定するときに、その名前を使うからです。
  • ダッシュボード → API キー で作る API キー。サーバー側に保管します。
  • tpl_kd93mz のような形のテンプレート ID。

呼び出し

エンドポイントは createPdf です。データを渡すと、PDF のバイト列が返ります。

<?php

$payload = [
    'apiKey' => getenv('BANNERIFY_API_KEY'),
    'templateId' => 'tpl_invoice',
    'modifications' => [
        ['name' => 'invoice-number', 'text' => 'INV-2026-0042'],
        ['name' => 'invoice-date', 'text' => '8 October 2026'],
        ['name' => 'customer-name', 'text' => 'Acme Studio'],
        ['name' => 'customer-address', 'text' => "12 Rue de Rivoli\n75001 Paris"],
        [
            'name' => 'line-items',
            'columns' => [
                ['key' => 'item', 'header' => 'Item'],
                ['key' => 'qty', 'header' => 'Qty', 'align' => 'right'],
                ['key' => 'amount', 'header' => 'Amount', 'align' => 'right'],
            ],
            'rows' => [
                ['item' => 'Automate plan, October', 'qty' => 1, 'amount' => '$29.00'],
                ['item' => 'Extra renders', 'qty' => 5, 'amount' => '$15.00'],
            ],
        ],
        ['name' => 'subtotal', 'text' => '$44.00'],
        ['name' => 'tax', 'text' => '$8.80'],
        ['name' => 'total', 'text' => '$52.80'],
        ['name' => 'pay-qr', 'qrcode' => 'https://pay.example.com/inv/2026-0042'],
    ],
];

$ch = curl_init('https://api.bannerify.co/v1/templates/createPdf');

curl_setopt_array($ch, [
    CURLOPT_POST => true,
    CURLOPT_RETURNTRANSFER => true,
    CURLOPT_HTTPHEADER => ['Content-Type: application/json'],
    CURLOPT_POSTFIELDS => json_encode($payload),
    CURLOPT_TIMEOUT => 30,
]);

$pdf = curl_exec($ch);
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);

if ($pdf === false || $status !== 200) {
    throw new RuntimeException("Invoice render failed with status {$status}");
}

file_put_contents("/invoices/INV-2026-0042.pdf", $pdf);

表のレイヤーが、ここの肝です。columns と rows を送ると、エディターで設定したスタイル(ストライプ、行の高さ、配置、ヘッダーのスタイル)が、届いたデータにそのまま適用されます。明細を 1 行足しても、レイアウトには触れません。表のレイヤーは画像でも使えるので、価格表やレポートにも役立ちます。表生成 API を見てください。

データの出どころ

上の形はわざと単純にしてあります。それが狙いで、データベースの行にそのまま対応するからです。

$lineItems = [];

foreach ($order['items'] as $item) {
    $lineItems[] = [
        'item' => $item['description'],
        'qty' => $item['quantity'],
        'amount' => '$' . number_format($item['subtotal'], 2),
    ];
}

$modifications[] = ['name' => 'line-items', 'rows' => $lineItems];

金額と日付は、送る前に自分の側で整えてください。テンプレートは通貨やロケールを推測しません。その処理は、おそらくお使いの請求コードにすでにあるはずです。

ストリーミングか、保存か

ファイルの渡し方は 2 通りあり、残しておきたいかどうかで選びます。

ブラウザにストリーミングする。 レスポンスは PDF そのものなので、適切なヘッダーを付けてそのまま流せます。

header('Content-Type: application/pdf');
header('Content-Disposition: inline; filename="INV-2026-0042.pdf"');
echo $pdf;

保存して URL を受け取る。 createStoredPdf は、描画した結果をアップロードして、メールに載せられるリンクを返します。

{ "url": "https://cdn.bannerify.co/invoices/..." }

請求書をメールで送るときに、ファイルの保管、期限付きリンク、S3 の権限を自分で管理したくないなら、この方法を使います。

押さえておきたいこと

  • レイヤー名は正確に。 line-items と line_items は別のレイヤーです。一致しないと、請求書のその部分はテンプレートの値のままになります。
  • 実際にいちばん長い請求書でテストする。 どの請求システムにも、いずれ明細が 40 行ある顧客が現れます。その書類は、問題が起きる前に確認しておきましょう。
  • 生成を冪等にする。 請求書番号をファイル名にして、ファイルがすでにあれば処理を飛ばします。同じ請求書を描画し直しても、何も起きないようにします。クォータをもう 1 回消費してはいけません。
  • API キーはサーバー側に置く。 請求書の生成は、ブラウザではなく、請求のコードの中で行います。

PDF ライブラリではだめなのか

ライブラリでも、もちろん作れます。多くのチームがそうしています。違いは、レイアウトがどこにあるかです。ライブラリなら、レイアウトは PHP の中にあります。デザイナーは触れず、ブランドを変えるたびに、デプロイとテストが必要です。テンプレートなら、レイアウトはエディターの中にあり、PHP はデータを運ぶだけです。

試行錯誤も速くなります。テンプレートを開き、合計のブロックを 2 センチ上に動かして、保存する。プルリクエストではなく、2 分で終わる変更です。

次のステップ

無料プランには、月 100 回の生成、テンプレート 1 つ、画像やファイルの保存容量 1GB が含まれます。これだけあれば、この仕組みを組み込んで、実際の請求書でテストできます。Automate は月 $29 から、3,000 回の生成まで使えます。詳しくは料金をご覧ください。

エンドポイントのパラメーターは、PDF 作成のリファレンスにあります。画像、QR コード、バーコード、グラフの行を含む modifications オブジェクトの全体像は、要素を見てください。同じパターンは、レシート、配送ラベル、証明書にも使えます。そのために作られているのが、PDF 生成 API です。

最初の 100 枚は無料です。

テンプレートを作り、API キーを取得すれば、数分で最初の画像を生成できます。