決済プラットフォームと経理を繋ぐ MoneyFlow

こんにちは、Merpay の Payment Core チームと Payment Solution チームで Engineering Manager (EM) をやっている komatsu です。普段は決済基盤や決済体験の開発をするチームを見ていたり、最近は PCP Foundation というチームを発足して Individual Contributor (IC) として基盤の整備や AI 周りのツールの導入も行っています。
この記事は Merpay & Mercoin Tech Openness Month 2026 の 4 日目の記事です。

この記事では、私たちの Payment Platform が「決済」と「会計」のあいだに置いている共通言語 MoneyFlow と、それを支えるために開発したツール群 mfgen (MoneyFlow Generator; /ˌemefˈdʒen/) について紹介します。一見すると別物に見える「システムとしての決済基盤」と「上場企業として厳密さが求められる会計」ですが、実際には深く結びついています。私たちは、その複雑な関係を整理し、経理・PdM・エンジニアといった異なる立場の人々が共通の理解を持てるよう、MoneyFlow という共通言語を整備してきました。この一年ほどで MoneyFlow は徐々に組織へ浸透し、現在では同じフォーマットで記述し、同じフォーマットでレビューする開発プロセスが少しずつ定着しつつあります。本記事では、その取り組みの背景と、それを支える mfgen の仕組みについて深掘りしていきます。

決済プラットフォームと会計のつながり

メルカリグループの Payment Platform は、メルカリのマーケットプレイス (Consumer to Consumer; CtoC) だけでなく、メルカリShops やメルペイ、メルコイン、メルカリモバイル、メルカリAds、グローバルアプリなど、「お金が動くすべてのプロダクト」の土台となり、決済にまつわる汎用的な機能を提供しています。決済そのものについての記事は多く上がっているので、興味があれば メルカリのグローバル展開を支えるPayment Platformの進化Payment に関するその他の記事 もあわせてご一読ください。

また、Payment Platform チームが掲げる理念の一つに「会計も含めた決済ソリューション」というものがあります。決済の一回一回は、お客さまや Payment Platform の利用者 (つまりプロダクトのマイクロサービス) から見れば「支払いが完了した」という体験です。しかし会社や経理から見れば、それは会計上の仕訳として正しく記録しなければならない事象でもあります。そこで Payment Platform は、外向きの決済 API を提供するだけでなく、その裏側で「お金がどう動き、どの勘定にどう記録されるか」までを引き受け、記帳や会計レポートの発行を通した社内向けの統合的な決済ソリューションとして存在しています。これによってプロダクトはビジネスロジックの開発に集中し、会計にまつわる大半の連携を Payment Platform に委ねることができます [^1]。

たとえば、メルカリのシンプルな購入ひとつを取っても、段階ごとにお金が動き、それぞれに対応する会計上の記録が発生します。お客さまが支払う場面では、残高を使う場合は購入者の資金移動口座からエスクロー決済の預かり金へと振り替え、メルペイのクレジットを使う場合はあと払い債権を計上し、他社クレジットカードを使う場合は PSP (Payment Service Provider) に対する未収入金として処理します。そして取引が完了して売上が立つ段階では、預かり金を取り崩し、出品者の資金移動口座と手数料収入へと振り分けます。

これはまだ単純な例ですが、実際には、コンビニ決済のような非同期な決済手段、キャンセルや返金、資金移動口座の開設有無、クーポン等による値引き、為替が絡む決済——こうした条件の組み合わせやタイミングの違いが絡み合い、仕訳はもっと複雑になります。特に、ひとつの API 呼び出しが複数の勘定に影響することもあれば、逆に、会計上はひとつの動きが複数の API にまたがることもある、という点も複雑性を増す要因となっています。この「ズレ」があるために、エンジニアと経理が直接話しても認識が噛み合わず、議論が長引くということが頻繁に起きていました。エンジニアが「決済 API のフロー」として見ているものを、経理は「仕訳」として見ており、同じ事象を、まったく異なる言語で眺めているからです。

MoneyFlow という共通言語

このすれ違いの根本にあるのは、Payment Platform のエンジニアと経理のあいだに横たわるドメイン的な距離です。両者は使う言葉からして異なり、エンジニアが API やエンドポイントで語るのに対し、経理は勘定科目や仕訳で語ります。前提とする知識も、システムの内部構造と会計基準というように噛み合いません。そのうえ、API と勘定科目が必ずしも 1:1 で対応しないため、片方の言葉をそのまま翻訳しても意味が通じないことがままあります。

この距離を埋めるために、Payment Platform で直近約一年にわたって運用しているのが MoneyFlow です。これはシステム上のお金の動きを表現するためのフロー図であり、同時に、エンジニア・経理・Product Manager (PdM) の理解を揃えるための共通言語でもあります。MoneyFlow は主に三つの要素で構成します。一つ目の Actor は取引の主体(誰が価値を出し、誰が受け取るのか)で、User (購入者や出品者)や Partner (加盟店さま等取引の相手方。社外事業者に限らず、会社として Mercari / Merpay / Mercoin もシステム上は Partner) が該当します。二つ目の Account は各 Actor が持つ勘定 (ledger) で、USER_FUNDSPARTNER_SALESUSER_DEBTPARTNER_CLEARING_SALES などがあります。三つ目の Flow はおおむね 1 回の API 呼び出しに相当するお金の移動を表し、Source (from) と Target (to) を持つことで、その決済でお金がどこからどこへ動くのかを示します。さらに各 Flow は、勘定科目に対応する accounting code を持ちます。

MoneyFlow example

こうした図として表現することで、エンジニアは価値交換を行う API を記述でき、経理は Flow を中心とした会計観点でのお金の動きを把握できます。図の Actors section は Actor の一覧とそれぞれが持つ Account (ledger) を表現し、MoneyFlow section は商流ごと・API ごとのお金の動きを表現します。

この一年ほどをかけて、MoneyFlow は徐々に組織に浸透してきました。現在では、経理・PdM・エンジニアが同じフォーマットで書き、同じフォーマットでレビューする、といった開発の工程が少しずつスタンダードになりつつあります。著者自身もプロジェクトや開発の最初のフェーズでこれを行うことで、ステークホルダーと認識を合わせやすくなったと実感しており、Design Doc に並ぶ重要なドキュメントだと感じています。さらに、エンジニアリングと会計の両面を表現する概念を持ったことで、エンジニアは会計のドメインを、経理はエンジニアのドメインを理解しやすくなりました。エンジニアが勘定科目について経理に相談したり、経理が API 名を使って商流を表現したりと、お互いの歩み寄りがかなり加速したと感じています。

mfgen CLI — DSL による MoneyFlow の標準化

組織への浸透が進む一方で、MoneyFlow は最初からフォーマットが決まっていたわけではありません。初期は Draw.io (Diagrams.net) で手描きしていました。これはこれで描けるのですが、いくつかの課題がありました。まず、書き方が人によって異なり、解像度や粒度が書き手に依存するため、図にばらつきが出ます。次に、そもそもどう書けばよいか分からない人がほとんどで、書ける人が限られていました。書ける人がいないプロジェクトでは、会計観点の考慮漏れを見落とすこともありました。さらに、Draw.io は XML で表現できるものの human-friendly な宣言的記法が存在せず、同じフォーマットで安定して描画することや AI agent との親和性に欠けていました。

そこでまず取り組んだのが、MoneyFlow を YAML の DSL として定義することでした。そして、その YAML から Draw.io (および PNG 画像) を生成する CLI ツール mfgen を開発しました。YAML は次のようなイメージです。

name: Example Payment Flow

actors:
  - id: user
    name: User
    type: USER
  - id: partner
    name: Partner
    type: PARTNER

accounts:
  - id: user_funds
    owner: user
    account_type: USER_FUNDS
    currency: JPY
  - id: partner_sales
    owner: partner
    account_type: PARTNER_SALES
    currency: JPY

flows:
  - id: MF1
    name: Payment
    api: Payment.CreateCharge
    currency: JPY
    accounting_code: xyz
    from:
      - id: user_funds
        amount: 1000
    to:
      - id: partner_sales
        amount: 1000

描画のクライアントとしては依然として Draw.io を使っているため、CLI の実装の中身はかなり地味なものです。YAML をパースし、描画に必要な座標を計算し、Draw.io の XML を組み立てる——レイアウトのための座標計算や XML 生成を、ひとつずつ実装した形になります。この段階では、validation を強めに設けて一貫性を高めることと、AI agent による生成を簡単にすることを目的としました。具体的には、次のチェックを行います。

  1. 必須フィールドを検証する
  2. ID の重複を検出する
  3. 参照整合性を確認する (actors の owner、flow の from / to などが実在するか)
  4. セマンティクスを検証する (from の合計と to の合計が一致するか、PARTNER_DEBT / USER_DEBTdebt_type があるか、など)

さらに、GitHub Actions で YAML を自動変換して Draw.io 形式および画像でアップロードする CI を組みました。これによってレビューや共有、過去の MoneyFlow の管理が簡単になり、MoneyFlow が蓄積されることで次の MoneyFlow 作成時の AI による精度も向上していきました。

mfgen Web — リアルタイム共同編集の実現

DSL 化によって標準化は大きく進みましたが、mfgen CLI にも残された課題がありました。変換が YAML → Draw.io の片方向であるため、図を見ながら直接編集して保存する、という使い方ができません。ミーティング中に Draw.io を直接編集したりコメントを付けたりすると、それを YAML に取り込むコストが発生します。そして、Draw.io の表現力そのものが上限になる場面もありました。

そこで開発したのが mfgen Web です。これは社内にホストしている Web ツールで、「Draw.io のような同時編集」と「YAML による宣言的な定義」の両方を実現します。具体的には、三つの編集方法を備えています。Canvas 上で直接描く方法では、Draw.io のようにノードを配置してつなぎます。MoneyFlow に特化した編集機能では、Actor / Account / Flow といったドメイン概念をそのまま編集できます。そして YAML を直接記述する方法では、エディタで宣言的に書けます。

これらはすべて双方向に同期します。YAML を更新すれば図に即座に反映され、図をドラッグすれば YAML にも反映されます。さらに、複数人が同じ MoneyFlow をリアルタイムで共同編集でき、メンバーが作成した MoneyFlow はカタログとして蓄積されていくため、チームのドキュメンテーションとしても活用できる形になりました。

mfgen Web

この手の内製ツールは Vibe Coding でおおよそ作れてしまう時代ですが、技術的なポイントを簡単に紹介します。

mfgen Web flow

サーバは役割の異なる 2 つに分かれています。api サーバ (Hono) が SPA の配信と REST API を担い、collab サーバ (Hocuspocus) が WebSocket での同時編集を担います。設計上のポイントは次のとおりです。

  • Single Source of Truth として Y.Doc (Conflict-free Replicated Data Type; CRDT) を採用する。サーバが権威ある Y.Doc を保持して各クライアントと同期し、YAML はサーバ側で Y.Doc から投影して生成する派生物とすることで、クライアントが直接書き込むことはありません。これにより、YAML を入力とする CLI 版 mfgen とのデータ互換性を保っています。
  • 「追記ログ + スナップショット」方式で永続化する。編集は append-only な update ログに追記し、2-10 秒程度の debounce で Y.Doc 全体のスナップショットと生成した YAML を Postgres に書き込み、古い update を圧縮 (compaction) します。
  • Canvas 上の座標を YAML から除外する。位置情報を YAML から外すことで、既存 CLI と等価なデータに保っています。
  • Origin タグ (5 種) で編集の出どころを区別する。「UI 操作」「YAML 編集」「ドラッグ操作」「他クライアントからの更新」「初期同期」をタグで見分け、双方向同期で起こりがちな無限ループを防ぎつつ、Undo の対象も制御しています。
  • Redis (Memorystore) の pub/sub で collab サーバ間のメッセージを fan-out する (@hocuspocus/extension-redis)。複数レプリカ運用に備えた仕組みで、単一レプリカであれば Redis なしでも動作します。

技術スタックは TypeScript / Bun に統一しています。フロントエンドは React + Vite + @xyflow/react + CodeMirror + Yjs、サーバは Hono + Hocuspocus + Drizzle ORM、データストアは Postgres と Memorystore Redis という構成です。これらを専用の Google Cloud プロジェクト上で、api / collab それぞれ独立したサービスとして運用しています。

mfgen Web はまだ開発したばかりで活用事例はありませんが、Web 版になったことで、MoneyFlow はより実践的なツールになると感じています。今後さらに開発を続け、エディタ内に Claude Code SDK などで AI を搭載したり、経理によるレビュー後にシステムへ登録するところまで E2E で自動化できるようになれば、会計がプロダクト開発のブロッカーにならず、基盤として素早いサポートができるようになると信じています。

まとめ

この記事では、Payment Platform が「会計も含めた決済ソリューション」であること、そしてエンジニアと経理のあいだを繋ぐ共通言語 MoneyFlow と、それを実践的に運用するための mfgen について紹介しました。MoneyFlow を共通の出発点に置いたことで、これまで噛み合わなかったエンジニアと経理の議論は、同じ図を指しながら進められるようになりました。考慮漏れが減り、お互いがお互いのドメインに歩み寄る——そうした定性的な変化が、この直近多く見られるようになったと感じています。

著者自身、会計はまだ勉強中の身ですが、システムと結びつけて考えるとかなり理解しやすくなる、というのが正直な実感です。そして、こうした内製ツールは AI の力を借りて本当に手軽に作れる時代になりました。私が所属する PCP Foundation チームでは、今後もこうした組織横断のツール開発とメンテナンスを通じて、チームの垣根を越えた生産性の向上につなげていきたいと思っています。

[^1]: 決済 API を利用するタイミングと会計連携のタイミングが異なる場合はプロダクトが直接行っているが、この深掘りと進化はまた別の機会に。

次の記事は hokao さんの「会計システムにおける訂正機能の設計と実装」です。引き続きお楽しみください。

  • X
  • Facebook
  • linkedin
  • このエントリーをはてなブックマークに追加