{
  "id": "sequence-diagram-idempotent-payment-authorization",
  "schemaVersion": 2,
  "title": {
    "ja": "決済の重複与信を防ぐ — 同一キーなら保存済み結果を返す",
    "en": "Prevent Duplicate Authorizations — Reuse the Stored Result for an Idempotency Key"
  },
  "summary": {
    "ja": "縦の時間順に参加者間の要求・応答を結び、与信前のキー照会と登録済み分岐の戻り先を示すシーケンス図",
    "en": "A sequence diagram connects requests and responses across participants in time order, showing the pre-authorization key check and duplicate branch."
  },
  "capturedAt": "2026-09-25",
  "categories": [
    "presentation"
  ],
  "tags": [
    "data-viz",
    "minimal"
  ],
  "useCases": [
    "architecture",
    "requirements"
  ],
  "format": "slide-16x9",
  "density": "medium",
  "layout": {
    "kind": "flow",
    "canvas": {
      "w": 1920,
      "h": 1080
    },
    "margin": {
      "top": 100,
      "right": 140,
      "bottom": 100,
      "left": 140
    }
  },
  "type": {
    "title": {
      "size": 46,
      "weight": 700,
      "tracking": "0.01em"
    },
    "subtitle": {
      "size": 22,
      "weight": 500
    },
    "axisTitle": {
      "size": 22,
      "weight": 700
    },
    "participant": {
      "size": 20,
      "weight": 700
    },
    "message": {
      "size": 20,
      "weight": 500
    },
    "condition": {
      "size": 20,
      "weight": 700
    },
    "takeaway": {
      "size": 28,
      "weight": 500
    },
    "note": {
      "size": 20,
      "weight": 400
    }
  },
  "colors": {
    "ground": "#FFFFFF",
    "surface": "#F4F6F9",
    "ink": "#131820",
    "muted": "#667183",
    "accent": "#1F5FA8",
    "rule": "#DBE1E9",
    "series": [
      "#1C8C79",
      "#A85A2E"
    ]
  },
  "rules": [
    {
      "ja": "縦の位置はメッセージの順番、縦破線は参加者の継続時間を示す",
      "en": "Vertical position is message order; dashed lifelines show each participant's span."
    },
    {
      "ja": "実線右向きは要求、破線左向きは応答を示す",
      "en": "Solid rightward arrows are requests; dashed leftward arrows are responses."
    },
    {
      "ja": "同一キー登録済みの分岐では保存結果を返し、決済ゲートウェイを再呼出ししない",
      "en": "When the same key is already registered, return the stored result without calling the payment gateway again."
    },
    {
      "ja": "架空シーケンス。実装時は並行要求の排他と失敗再試行の規則を定義する",
      "en": "Fictional sequence. Define concurrency control and retry rules for failures in a real implementation."
    }
  ],
  "cover": "https://design-vault.pages.dev/_astro/cover.Bx5TWlZb.png",
  "assets": [],
  "shortlist": false,
  "status": "published",
  "relations": {
    "similar": []
  },
  "license": "Original",
  "publishedAt": null,
  "reproduction": {
    "spec": {
      "format": "slide-16x9",
      "density": "medium",
      "layout": {
        "kind": "flow",
        "canvas": {
          "w": 1920,
          "h": 1080
        },
        "margin": {
          "top": 100,
          "right": 140,
          "bottom": 100,
          "left": 140
        }
      },
      "type": {
        "title": {
          "size": 46,
          "weight": 700,
          "tracking": "0.01em"
        },
        "subtitle": {
          "size": 22,
          "weight": 500
        },
        "axisTitle": {
          "size": 22,
          "weight": 700
        },
        "participant": {
          "size": 20,
          "weight": 700
        },
        "message": {
          "size": 20,
          "weight": 500
        },
        "condition": {
          "size": 20,
          "weight": 700
        },
        "takeaway": {
          "size": 28,
          "weight": 500
        },
        "note": {
          "size": 20,
          "weight": 400
        }
      },
      "colors": {
        "ground": "#FFFFFF",
        "surface": "#F4F6F9",
        "ink": "#131820",
        "muted": "#667183",
        "accent": "#1F5FA8",
        "rule": "#DBE1E9",
        "series": [
          "#1C8C79",
          "#A85A2E"
        ]
      },
      "rules": [
        "Vertical position is message order; dashed lifelines show each participant's span.",
        "Solid rightward arrows are requests; dashed leftward arrows are responses.",
        "When the same key is already registered, return the stored result without calling the payment gateway again.",
        "Fictional sequence. Define concurrency control and retry rules for failures in a real implementation."
      ]
    },
    "prompt": {
      "ja": "以下の仕様でスライドを 1 枚作ってください。\n\n- 版面 1920 × 1080\n- 余白 上 100 右 140 下 100 左 140\n\n## 文字（版面 1920px に対する px）\ntitle  46px / 700 / 字間 0.01em\nsubtitle  22px / 500\naxisTitle  22px / 700\nparticipant  20px / 700\nmessage  20px / 500\ncondition  20px / 700\ntakeaway  28px / 500\nnote  20px / 400\n\n## 配色\n地 #FFFFFF / 面 #F4F6F9 / 文字 #131820 / 補助 #667183 / 強調 #1F5FA8 / 罫 #DBE1E9 / #1C8C79 / #A85A2E\n\n## 外すと崩れる点\n- 縦の位置はメッセージの順番、縦破線は参加者の継続時間を示す\n- 実線右向きは要求、破線左向きは応答を示す\n- 同一キー登録済みの分岐では保存結果を返し、決済ゲートウェイを再呼出ししない\n- 架空シーケンス。実装時は並行要求の排他と失敗再試行の規則を定義する\n\n内容は［ここに自分の内容を書く］に置き換えてください。寸法と配色はそのまま守ってください。\n正確に再現する場合は、この HTML をそのまま使ってください: https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/pattern.html",
      "en": "Produce one slide to the following specification.\n\n- Canvas 1920 × 1080\n- Margin top 100 right 140 bottom 100 left 140\n\n## Type (px against a 1920px canvas)\ntitle  46px / 700 / tracking 0.01em\nsubtitle  22px / 500\naxisTitle  22px / 700\nparticipant  20px / 700\nmessage  20px / 500\ncondition  20px / 700\ntakeaway  28px / 500\nnote  20px / 400\n\n## Colour\nGround #FFFFFF / Surface #F4F6F9 / Ink #131820 / Muted #667183 / Accent #1F5FA8 / Rule #DBE1E9 / #1C8C79 / #A85A2E\n\n## Constraints — dropping these breaks it\n- Vertical position is message order; dashed lifelines show each participant's span.\n- Solid rightward arrows are requests; dashed leftward arrows are responses.\n- When the same key is already registered, return the stored result without calling the payment gateway again.\n- Fictional sequence. Define concurrency control and retry rules for failures in a real implementation.\n\nReplace the content with [your content]. Keep the measurements and colours as given.\nFor an exact reproduction, use the verbatim HTML at https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/pattern.html."
    },
    "code": {
      "html": "<!doctype html><meta charset=\"utf-8\"><title>決済の重複与信を防ぐ — 同一キーなら保存済み結果を返す</title><meta name=\"dv-font\" content=\"Zen Kaku Gothic New:400;500;700\"><link rel=\"stylesheet\" href=\"./font.css\"><style>:root{--ground:#FFFFFF;--surface:#F4F6F9;--ink:#131820;--muted:#667183;--accent:#1F5FA8;--rule:#DBE1E9;--series-1:#1C8C79;--series-2:#A85A2E;}*{box-sizing:border-box;margin:0}html,body{width:1920px;height:1080px}body{font-family:\"Zen Kaku Gothic New\",\"Hiragino Sans\",sans-serif}.artboard{width:1920px;height:1080px;padding:100px 140px;background:var(--ground);color:var(--ink)}.content{width:100%;height:100%;position:relative}.figure{position:absolute;left:-140px;top:-100px;width:1920px;height:1080px}</style><div class=\"artboard\" data-artboard><div class=\"content\" data-content><svg class=\"figure\" width=\"1920\" height=\"1080\" viewBox=\"0 0 1920 1080\" xmlns=\"http://www.w3.org/2000/svg\" role=\"img\" aria-label=\"決済のシーケンス図。顧客から購入画面、支払API、キー保管、決済ゲートウェイへ進み、同一キーが登録済みなら外部与信を再実行せず保存済み結果を返す分岐を示す。\"><defs><marker id=\"right\" markerWidth=\"10\" markerHeight=\"10\" refX=\"9\" refY=\"5\" orient=\"auto\"><path d=\"M 0 0 L 10 5 L 0 10 Z\" fill=\"var(--accent)\"/></marker><marker id=\"left\" markerWidth=\"10\" markerHeight=\"10\" refX=\"9\" refY=\"5\" orient=\"auto\"><path d=\"M 0 0 L 10 5 L 0 10 Z\" fill=\"var(--muted)\"/></marker></defs><style>.figure{font-family:\"Zen Kaku Gothic New\",\"Hiragino Sans\",sans-serif}.ground{fill:var(--ground)}.ink{fill:var(--ink)}.muted{fill:var(--muted)}.rule{stroke:var(--rule)}.title{font-size:46px;font-weight:700;letter-spacing:.01em}.subtitle{font-size:22px;font-weight:500}.axis-title{font-size:22px;font-weight:700}.participant{font-size:20px;font-weight:700}.message-label{font-size:20px;font-weight:500}.condition{font-size:20px;font-weight:700}.takeaway{font-size:28px;font-weight:500}.note{font-size:20px;font-weight:400}.actor{fill:var(--surface);stroke:var(--rule);stroke-width:1.5}.life{stroke:var(--rule);stroke-width:2;stroke-dasharray:7 7}.request{stroke:var(--accent);stroke-width:2.5}.response{stroke:var(--muted);stroke-width:2.5;stroke-dasharray:8 5}.label-bg{fill:var(--ground)}.frame{fill:none;stroke:var(--muted);stroke-width:2}.surface{fill:var(--surface)}.frame-divider{stroke:var(--rule);stroke-width:1.5;stroke-dasharray:7 5}</style><rect class=\"ground\" width=\"1920\" height=\"1080\"/><text class=\"ink title\" data-type=\"title\" x=\"140\" y=\"153\">決済の重複与信を防ぐ — 同一キーなら保存済み結果を返す</text><text class=\"muted subtitle\" data-type=\"subtitle\" x=\"140\" y=\"201\">顧客 → 購入画面 → 支払API → キー保管 → 決済GW / 架空シーケンス</text><line class=\"rule\" x1=\"140\" y1=\"238\" x2=\"1780\" y2=\"238\" stroke-width=\"2\"/><text class=\"ink axis-title\" data-type=\"axisTitle\" x=\"960\" y=\"294\" text-anchor=\"middle\">時間は上から下へ — 矢印は要求と戻り値の順序を示す</text><line class=\"life\" x1=\"260\" y1=\"376\" x2=\"260\" y2=\"922\"/><line class=\"life\" x1=\"610\" y1=\"376\" x2=\"610\" y2=\"922\"/><line class=\"life\" x1=\"960\" y1=\"376\" x2=\"960\" y2=\"922\"/><line class=\"life\" x1=\"1310\" y1=\"376\" x2=\"1310\" y2=\"922\"/><line class=\"life\" x1=\"1660\" y1=\"376\" x2=\"1660\" y2=\"922\"/><rect class=\"actor\" x=\"155\" y=\"322\" width=\"210\" height=\"54\" rx=\"14\"/><text class=\"ink participant\" data-type=\"participant\" x=\"260\" y=\"349\" text-anchor=\"middle\" dominant-baseline=\"central\">顧客</text><rect class=\"actor\" x=\"505\" y=\"322\" width=\"210\" height=\"54\" rx=\"14\"/><text class=\"ink participant\" data-type=\"participant\" x=\"610\" y=\"349\" text-anchor=\"middle\" dominant-baseline=\"central\">購入画面</text><rect class=\"actor\" x=\"855\" y=\"322\" width=\"210\" height=\"54\" rx=\"14\"/><text class=\"ink participant\" data-type=\"participant\" x=\"960\" y=\"349\" text-anchor=\"middle\" dominant-baseline=\"central\">支払API</text><rect class=\"actor\" x=\"1205\" y=\"322\" width=\"210\" height=\"54\" rx=\"14\"/><text class=\"ink participant\" data-type=\"participant\" x=\"1310\" y=\"349\" text-anchor=\"middle\" dominant-baseline=\"central\">キー保管</text><rect class=\"actor\" x=\"1555\" y=\"322\" width=\"210\" height=\"54\" rx=\"14\"/><text class=\"ink participant\" data-type=\"participant\" x=\"1660\" y=\"349\" text-anchor=\"middle\" dominant-baseline=\"central\">決済GW</text><rect class=\"frame\" x=\"575\" y=\"540\" width=\"1113\" height=\"332\" rx=\"8\"/><rect class=\"surface\" x=\"575\" y=\"540\" width=\"1113\" height=\"42\" rx=\"8\"/><text class=\"ink condition\" data-type=\"condition\" x=\"595\" y=\"561\" dominant-baseline=\"central\">alt</text><text class=\"muted condition\" x=\"650\" y=\"561\" dominant-baseline=\"central\">初回キー・未登録</text><line class=\"frame-divider\" x1=\"575\" y1=\"723\" x2=\"1688\" y2=\"723\"/><text class=\"ink condition\" x=\"595\" y=\"744\" dominant-baseline=\"central\">else</text><text class=\"muted condition\" x=\"650\" y=\"744\" dominant-baseline=\"central\">同一キーを再送・登録済み</text><line class=\"message request\" x1=\"260\" y1=\"390\" x2=\"610\" y2=\"390\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"370\" y=\"357\" width=\"130\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"435\" y=\"370\" text-anchor=\"middle\" dominant-baseline=\"central\">購入を確定</text><line class=\"message request\" x1=\"610\" y1=\"435\" x2=\"960\" y2=\"435\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"615\" y=\"402\" width=\"340\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"785\" y=\"415\" text-anchor=\"middle\" dominant-baseline=\"central\">POST /authorize（key K-204）</text><line class=\"message request\" x1=\"960\" y1=\"480\" x2=\"1310\" y2=\"480\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"1026\" y=\"447\" width=\"218\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1135\" y=\"460\" text-anchor=\"middle\" dominant-baseline=\"central\">K-204 を検索</text><line class=\"message response\" x1=\"1310\" y1=\"515\" x2=\"960\" y2=\"515\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"1092\" y=\"482\" width=\"86\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1135\" y=\"495\" text-anchor=\"middle\" dominant-baseline=\"central\">未登録</text><line class=\"message request\" x1=\"960\" y1=\"615\" x2=\"1660\" y2=\"615\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"1245\" y=\"582\" width=\"130\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1310\" y=\"595\" text-anchor=\"middle\" dominant-baseline=\"central\">与信を要求</text><line class=\"message response\" x1=\"1660\" y1=\"648\" x2=\"960\" y2=\"648\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"1179\" y=\"615\" width=\"262\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1310\" y=\"628\" text-anchor=\"middle\" dominant-baseline=\"central\">承認 auth-731</text><line class=\"message request\" x1=\"960\" y1=\"681\" x2=\"1310\" y2=\"681\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"1048\" y=\"648\" width=\"174\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1135\" y=\"661\" text-anchor=\"middle\" dominant-baseline=\"central\">承認結果を保存</text><line class=\"message response\" x1=\"960\" y1=\"711\" x2=\"610\" y2=\"711\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"654\" y=\"678\" width=\"262\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"785\" y=\"691\" text-anchor=\"middle\" dominant-baseline=\"central\">成功 auth-731</text><line class=\"message request\" x1=\"960\" y1=\"786\" x2=\"1310\" y2=\"786\" marker-end=\"url(#right)\"/><rect class=\"label-bg\" x=\"1026\" y=\"753\" width=\"218\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1135\" y=\"766\" text-anchor=\"middle\" dominant-baseline=\"central\">保存済み結果を取得</text><line class=\"message response\" x1=\"1310\" y1=\"821\" x2=\"960\" y2=\"821\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"993\" y=\"788\" width=\"284\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"1135\" y=\"801\" text-anchor=\"middle\" dominant-baseline=\"central\">auth-731 を返却</text><line class=\"message response\" x1=\"960\" y1=\"856\" x2=\"610\" y2=\"856\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"676\" y=\"823\" width=\"218\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"785\" y=\"836\" text-anchor=\"middle\" dominant-baseline=\"central\">同じ成功結果を返す</text><line class=\"message response\" x1=\"610\" y1=\"906\" x2=\"260\" y2=\"906\" marker-end=\"url(#left)\"/><rect class=\"label-bg\" x=\"348\" y=\"873\" width=\"174\" height=\"27\" rx=\"4\"/><text class=\"ink message-label\" data-type=\"message\" x=\"435\" y=\"886\" text-anchor=\"middle\" dominant-baseline=\"central\">注文受付を表示</text><text class=\"ink takeaway\" data-type=\"takeaway\" x=\"960\" y=\"950\" text-anchor=\"middle\">保存キーを先に照会 — 登録済みなら決済GWへ再送しない</text><line class=\"rule\" x1=\"140\" y1=\"987\" x2=\"1780\" y2=\"987\" stroke-width=\"1\"/><text class=\"muted note\" data-type=\"note\" x=\"140\" y=\"1022\">応答順序の例示。実装では同時再送時の排他・失敗時の再試行規則も別途定義する。</text></svg></div></div>",
      "url": "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/pattern.html",
      "fonts": [
        "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/font.css",
        "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/font-0.woff2",
        "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/font-1.woff2",
        "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/font-2.woff2"
      ]
    }
  },
  "urls": {
    "ja": "https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization",
    "en": "https://design-vault.pages.dev/en/designs/sequence-diagram-idempotent-payment-authorization"
  },
  "notesMarkdown": "### 視覚的な問い\n\n決済リクエストの重複をどこで検出し、初回と再送でどの順に応答するか。\n\n### 構造\n\n参加者ごとに縦のライフラインを置き、時間を上から下へ進める。実線の要求が右へ進み、破線の応答が左へ戻る。キー保管の照会結果を受けて、未登録なら決済GWへ与信要求と保存済み結果の記録を行い、同一キーが登録済みなら保存結果を購入画面へ返す。\n\nキーの照会を外部与信の前に置くことで、重複再送が新しい与信処理へ進まない境界を明示する。工程の節点を列挙するprocess-flowや、システム間を概観するsystem-landscape mapと異なり、このシーケンス図は参加者間のメッセージ順と条件分岐を示す。架空の要求例で、実装には同時要求の排他・失敗時の再試行規則が別途必要となる。"
}