Claude Media
Claude CodeでStripe入金を消込する — 入金照合CSVから仕訳候補まで

Claude CodeでStripe入金を消込する — 入金照合CSVから仕訳候補まで

Stripeの入金照合レポートの明細CSVを入金単位に束ね、銀行の入金額と突き合わせて手数料・返金・不審請求を内訳にした仕訳候補を出すスクリプトを、Claude Codeで作る手順です。

Stripeの入金(payout)を銀行口座の入金額と合わせるには、入金に含まれる取引を一件ずつ束ね直す作業が要ります。銀行に着く金額は、売上の総額から手数料・返金・不審請求の引き落としを差し引いた後の額だからです。この束ね直しは、ダッシュボードで落とした明細CSVを入金単位で集計するスクリプトにして、Claude Codeに書かせ、実行まで回させると毎月同じ基準で終わります。

この記事では、入金照合レポートの明細CSVを automatic_payout_id ごとに集計し、銀行の入金データと突合して、一致した入金には仕訳候補を、一致しなかった入金には原因を探す手がかりを出す流れを作ります。サンプルデータで動かした出力も載せます。

入金照合レポートの明細CSVが起点になる

Stripeの入金照合レポートは、銀行口座に着いた入金を、その入金に含まれる支払い・返金・不審請求・手数料などの取引と照合するためのレポートです。入金照合のセクションでは、選んだ期間の自動入金が入金ごとの内訳で並び、取引はレポートカテゴリ別にまとまっています。ダウンロード形式はサマリーと明細の2つで、消込に使うのは明細のほうです。サマリーは画面に出ている合計値、明細は合計に入っているすべての取引だからです。

このレポートには使える条件があります。

  • 自動入金を有効にしているアカウントが対象です。自動入金を有効にしている連結アカウントを持つプラットフォームも使えます。
  • 手動入金を使っている場合や、銀行口座のようにStripe残高の出入りを追いたい場合は、入金照合ではなく残高レポートを使います。
  • 即時入金は取引との対応が付きません。即時入金は金額とタイミングを利用者が決めるため、どの取引が含まれるかをStripeが識別できず、取引履歴との照合は利用者の責任とされています。

つまり、この記事の手順は「自動入金で毎営業日・毎週など定期的に着金している口座」の消込にだけ当てはまります。即時入金を併用している場合は、その分の行を別に拾う作業が残ります。

銀行の計上日ではなく到着予定日で束ねられる

レポートは、銀行が入金を計上した日ではなく、入金ページに出る到着予定日で入金をグループ化します。期間を選ぶときも到着予定日を基準にします。到着予定日が分からないときは、期間を広げて探す扱いです。

実際の資金は週末・祝日・銀行の処理で後ろにずれることがあります。銀行CSVの日付と明細CSVの automatic_payout_effective_at を完全一致で結ぶと、ずれた入金がすべて未一致になります。照合では金額を主キー、日付は数日の許容幅つきにします。

明細CSVから読む列を決める

明細(項目別入金照合)には多くの列がありますが、消込に必要なのは次の列です。いずれも既定でダウンロードに含まれる列です。

列中身消込での使いどころ
automatic_payout_id中身入金のID消込での使いどころ入金単位で束ねるキー
automatic_payout_effective_at中身入金の到着予定日消込での使いどころ銀行の日付との許容幅つき照合
balance_transaction_id中身残高取引のID消込での使いどころ行の特定。差異の調査用
reporting_category中身取引のレポートカテゴリ消込での使いどころ売上・返金・不審請求の振り分け
gross / fee / net中身総額・手数料・差引額消込での使いどころ集計の素材
currency中身通貨消込での使いどころ通貨ごとに分けて集計

customer_email や customer_name、カードの住所などの個人に結びつく列は、既定ではダウンロードに入りません。消込にも使わないので、列のカスタマイズを触らないまま使うのが安全です。payment_metadata[key] のようにメタデータの列は、列名にキーを指定して追加できます。会計システム側の請求IDをメタデータに入れてある場合は、後でそのキーを足して請求との突合に使えます。

金額は通貨の主単位で出ます。円なら円の整数、ドルならセントではなくドルの小数です。スクリプトで int() に通せるのは円建てだけです。ドル建ての入金もあるアカウントでは、Decimal で読み、通貨ごとに集計を分けます。

最初にClaude Codeへ実CSVの中身を調べさせる

照合ロジックを書かせる前に、実際のCSVで reporting_category にどんな値が入っているかを確かめます。次のコードの DEBIT に置いた refund や dispute は、サンプルで使った仮の値です。自分のCSVの値と違えば、辞書の左側を実物に直します。

claude -p "itemized.csv の reporting_category の値を、件数とgrossの合計つきで\
一覧にして。行の内容そのものは出力しないで" \
  --allowedTools "Bash(python3 *)"

この問い合わせでは、顧客に結びつく列を出力に載せないよう指示しています。実データの一行をそのまま会話に貼らせず、件数と合計で報告させる運用にしておくと、後の工程で請求先名などが回答に残りにくくなります。

CLAUDE.mdに照合の規約を置く

毎回の指示で繰り返すことになる規約は、CLAUDE.md に置きます。

# Stripe入金消込の規約
- 照合ルールは payout_recon.py に実装し、モデルが金額を目視で突き合わせない
- 入金は automatic_payout_id で束ね、net の合計と銀行の入金額を比べる
- 日付は到着予定日から3日以内の銀行入金を候補にする。金額は完全一致のみ
- 通貨ごとに集計を分ける。通貨をまたいだ合算をしない
- reporting_category は実CSVの値で辞書を作る。辞書にないカテゴリは「未知」と表示し、その入金の仕訳を出さない
- 仕訳は候補として出す。確定は人が行う
- 実データの行を回答に貼らず、件数と区分で報告する

「辞書にないカテゴリは未知で止める」の1行が要です。未知のカテゴリを黙って売上に含めると、貸借の合計は合ったように見えて、科目だけが間違った仕訳が残ります。

入金単位の照合スクリプト

次のスクリプトは、上の規約で書かせる実装の一例です。標準ライブラリだけで動きます。勘定科目の名前は自社の科目に合わせて直す部分です。

import csv, sys
from collections import defaultdict
from datetime import date
 
# reporting_category -> 借方の勘定科目候補(実CSVの値に合わせて直す)
DEBIT = {"refund": "売上返金", "dispute": "紛争損失"}
CREDIT_CATEGORIES = {"charge"}  # 売上として貸方に立てるカテゴリ
TOLERANCE_DAYS = 3  # 到着予定日から銀行計上日までの許容日数
 
def rows(path):
    with open(path, encoding="utf-8-sig", newline="") as f:
        return list(csv.DictReader(f))
 
payouts = defaultdict(lambda: {"gross": defaultdict(int), "fee": 0, "net": 0})
for r in rows(sys.argv[1]):
    p = payouts[(r["automatic_payout_id"], r["automatic_payout_effective_at"])]
    p["gross"][r["reporting_category"]] += int(r["gross"])
    p["fee"] += int(r["fee"])
    p["net"] += int(r["net"])
 
bank = rows(sys.argv[2])
def d(s): return date.fromisoformat(s)
 
used = set()
for (pid, eff), p in sorted(payouts.items(), key=lambda x: x[0][1]):
    hit = [b for b in bank if int(b["amount"]) == p["net"]
           and 0 <= (d(b["date"]) - d(eff)).days <= TOLERANCE_DAYS]
    used.update(id(b) for b in hit[:1])
    status = "一致" if hit else "不一致"
    print(f"{pid} 到着予定{eff} net={p['net']} "
          f"銀行={hit[0]['date'] if hit else '-'} {status}")
    if not hit:
        near = [b for b in bank if abs(int(b["amount"]) - p["net"]) <= 100]
        print("  近い入金:", [(b["date"], b["amount"]) for b in near])
        continue
    unknown = set(p["gross"]) - CREDIT_CATEGORIES - set(DEBIT)
    if unknown:
        print("  未知カテゴリ:", unknown, "-> 仕訳を出さずに止める")
        continue
    lines = [("借", "普通預金", p["net"]), ("借", "支払手数料", p["fee"])]
    for cat, amt in p["gross"].items():
        if cat in DEBIT:
            lines.append(("借", DEBIT[cat], -amt))
    credit = sum(p["gross"][c] for c in CREDIT_CATEGORIES)
    lines.append(("貸", "売上", credit))
    dr = sum(a for s, _, a in lines if s == "借")
    for s, name, a in lines:
        print(f"  {s} {name} {a}")
    print("  貸借", "一致" if dr == credit else f"差 {dr - credit}")
 
for b in bank:
    if id(b) not in used:
        print("銀行側に対応する入金なし:", b["date"], b["amount"], b["memo"])

入力は2つのCSVです。itemized.csv は入金照合レポートの明細から必要な列だけを残したもの、bank.csv は銀行の入金明細を date, amount, memo の3列に揃えたものです。銀行CSVの文字コードや列名は銀行ごとに違うので、変換は別のスクリプトに切り出すと、照合ルールの変更と入力形式の変更を切り離せます。変換の書き方は入金消込をClaude Codeで自動化する記事にある例が、そのまま使えます。

実行結果の読み方

入金2件・取引7行のサンプルデータ(架空)で動かします。1件目は売上3件・返金1件・不審請求1件、2件目は売上2件です。銀行側は、2件目だけ8円少ない入金を置いてあります。

python3 payout_recon.py itemized.csv bank.csv
po_A1 到着予定2026-10-05 net=18740 銀行=2026-10-06 一致
  借 普通預金 18740
  借 支払手数料 1260
  借 売上返金 5000
  借 紛争損失 10000
  貸 売上 35000
  貸借 一致
po_B2 到着予定2026-10-12 net=40488 銀行=- 不一致
  近い入金: [('2026-10-13', '40480')]
銀行側に対応する入金なし: 2026-10-13 40480 ストライプ
銀行側に対応する入金なし: 2026-10-14 1500 ストライプ

po_A1 は、到着予定日の翌日に着いた18,740円と net の合計が合い、貸借も一致しました。総額35,000円の売上から、手数料1,260円、返金5,000円、不審請求10,000円が引かれた結果が18,740円です。

po_B2 は一致しません。net の合計は40,488円で、銀行には8円少ない40,480円が着いています。スクリプトは金額が近い入金を表示して止まります。8円差を端数として丸めて消し込む処理は、あえて入れていません。差額の幅を許すと、入金漏れや取引行の欠落まで一緒に消えるからです。

最後の2行は逆方向の確認です。銀行にはあるのにStripe側の入金と結べなかった行が出ます。1,500円の入金は、サンプルでは即時入金を想定した行です。即時入金は入金照合の明細に取引との対応が付かないため、ここに残ります。メモ欄にStripeとあるのに結べない行は、こうして洗い出します。

切り分け

不一致の入金は上から順に確かめる

  1. QCSVの期間に、その入金の取引が欠けなく入っているか?
    答えがいいえのとき

    期間を広げてダウンロードし直します。レポートの期間は到着予定日で選ぶ仕様なので、前後の日付まで含めます。

    答えがはい
  2. Q銀行側の日付は到着予定日から許容日数以内か?
    答えがいいえのとき

    週末や祝日をまたぐと許容日数を超えることがあります。TOLERANCE_DAYS を一時的に広げ、金額が一致するかだけを見ます。

    答えがはい
  3. Q金額が近い入金が銀行側にあるか?
    答えがいいえのとき

    即時入金や手動入金が混ざっていないかを疑います。これらは入金照合レポートの対象外か、取引との対応をStripeが識別できないものです。

    答えがはい

それでも差額が残る

差額と対象の automatic_payout_id を残して、人が balance_transaction_id の単位で確認します。

仕訳候補の組み方

仕訳は、入金ごとに総額・手数料・返金・不審請求を分けて立てます。

項目借方貸方元になる値
銀行に着いた額借方普通預金貸方元になる値net の合計
決済手数料借方支払手数料貸方元になる値fee の合計
返金借方売上返金貸方元になる値カテゴリが返金の gross(符号を反転)
不審請求借方紛争損失貸方元になる値カテゴリが不審請求の gross(符号を反転)
売上の総額借方貸方売上元になる値カテゴリが支払いの gross の合計

借方の合計が貸方の売上と一致すれば、その入金の内訳に過不足がありません。スクリプトが最後に出す「貸借」の行がその検算です。一致しなければ、辞書にない取引の種類が混ざっているか、集計の対象外にした行があります。

注意点が1つあります。withheld_tax の列は、源泉(差し引き)された売上税・VAT・GSTの額です。その金額はすでに fee に含まれます。この列に値が入るアカウントでは、手数料の中の税額を別科目に分けるかどうかを、税理士の方針に合わせて決める必要があります。スクリプトの fee は税額込みの合計なので、分ける場合は fee_net_of_withheld_tax の列を足して差を取ります。

出した仕訳はあくまで候補です。売上の計上時期や、Stripe残高を経由する経理方式による科目の違いは、会計方針で決まります。スクリプトに固定せず、DEBIT と科目名の定数を差し替える形にしておくと、方針が変わったときも手戻りが少なくて済みます。Stripeの不審請求そのものへの対応は不審請求の反証資料の手順にまとめてあります。

月次で無人実行する

照合の結果は決まった形のテキストなので、毎月の実行はスクリプトに任せ、Claude Codeには「不一致の整理」だけを頼むと安定します。非対話モード(-p)は標準入力を読めるので、結果をパイプで渡せます。

python3 payout_recon.py itemized.csv bank.csv > recon.txt
cat recon.txt | claude -p "不一致の入金と銀行側の対応なし入金を、\
確認する順に並べ、原因の候補を各1行で書いて" \
  --output-format json | jq -r '.result'

標準入力から渡せるのは10MBまでで、超えるとエラーで終了します。1か月分の集計結果はそれよりずっと小さいので問題になりませんが、明細CSVそのものを丸ごと渡す設計にすると到達します。大きい入力はファイルに書き、プロンプトにはパスだけを書きます。

スクリプトの実行までClaude Codeに任せるなら、Bashの許可を先に決めます。

claude -p "今月分の入金を照合して、不一致を報告して" \
  --allowedTools "Bash(python3 payout_recon.py *)" \
  --permission-prompts none

--allowedTools の末尾の * は、その接頭辞で始まるコマンドを許可する書き方です。--permission-prompts none は、承認する人がいない定期実行で、許可に当たらない操作を拒否して先へ進むためのフラグで、Claude Code v2.1.259以降で使えます。定期実行で CLAUDE.md やhooksを読ませたくないときは --bare も使えますが、--bare はサブスクリプションのログインを使わず、ANTHROPIC_API_KEY が必要です。

つまずきやすい点

レポートの準備より先に入金が着く。レポートデータは別の処理スケジュールで作られるため、照合データがそろう前に入金が到着することがあります。月初に前月分をまとめて処理するときは、最終日の入金まで明細に入っているかを先に確認します。

失敗した入金。入金照合レポートには、失敗した自動入金を別にまとめる失敗した入金のセクションがあります。選んだ期間内に失敗した自動入金がある場合にだけ出るので、銀行に着かなかった入金は、ここで探します。

期末の残高。月末時点でまだ入金に回っていない取引は、最終残高の照合のセクションに出ます。レポートの最終日時点で売上処理されていない取引の内訳なので、月末をまたぐ取引の確認に使えます。

ダッシュボードの期間は1日単位。ダッシュボード上の入金照合レポートは常に1日単位で、期間をまとめて取りたい場合はReporting APIを使います。毎月の定期実行をAPIから組むなら、新しいデータが用意されたときにStripeが送る reporting.report_type.updated のwebhookを受けて走らせる形も取れます。受信側の作りはStripe webhookの冪等受信の記事が参考になります。

まとめ

入金の消込は、金額を見比べる作業ではなく、入金に含まれる取引を束ね直して銀行の額に合わせる集計です。束ね直しのキーは automatic_payout_id、日付は到着予定日に許容幅をつける、金額は完全一致のみ、の3点を固定し、残った差額は人が balance_transaction_id まで降りて確認します。Claude Codeに任せるのは、スクリプトを書くことと、不一致の整理までです。

最初に作る価値があるのは、辞書にないカテゴリで止まる処理です。仕訳が貸借一致に見えても、カテゴリの振り分けが一つ違えば科目が違う仕訳が残ります。

参照した一次ソース

この記事の記述は、次の一次ソースと照合しています。更新時に参照先が変わった場合は一覧も更新します。

  1. docs.stripe.com/reports/payout-reconciliation
  2. code.claude.com/docs/en/headless
この記事を共有:XはてブLinkedIn