Design Vault Search use case, structure, colour, notes /
Index Categories Tags 日本語
Back to index

Prevent Duplicate Authorizations — Reuse the Stored Result for an Idempotency Key

Flow
Prevent Duplicate Authorizations — Reuse the Stored Result for an Idempotency Key
140 100

1920 × 1080 Seen as a design

Take it with you

Copy and paste, or save a file and hand it over. For a machine with no network, one “Everything” file is enough.

Everything

sequence-diagram-idempotent-payment-authorization-everything.md

Everything in this panel, including the contents behind each URL, in one Markdown file

Prompt

1.1 KB
Produce one slide to the following specification.

- Canvas 1920 × 1080
- Margin top 100 right 140 bottom 100 left 140

## Type (px against a 1920px canvas)
title  46px / 700 / tracking 0.01em
subtitle  22px / 500
axisTitle  22px / 700
participant  20px / 700
message  20px / 500
condition  20px / 700
takeaway  28px / 500
note  20px / 400

## Colour
Ground #FFFFFF / Surface #F4F6F9 / Ink #131820 / Muted #667183 / Accent #1F5FA8 / Rule #DBE1E9 / #1C8C79 / #A85A2E

## Constraints — dropping these breaks it
- 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.

Replace the content with [your content]. Keep the measurements and colours as given.
For an exact reproduction, use the verbatim HTML at https://design-vault.pages.dev/designs/sequence-diagram-idempotent-payment-authorization/pattern.html.

Spec

1.4 KB

/ai/designs/sequence-diagram-idempotent-payment-authorization.json

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.

Files

pattern.html

8.9 KB

/designs/sequence-diagram-idempotent-payment-authorization/pattern.html — The artboard itself, font subset included — open it and this picture draws.

Show contents
<!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>

font.css

3.9 KB

/designs/sequence-diagram-idempotent-payment-authorization/font.css — Not in Everything

Show contents
/* dv-subset v2 — generated by scripts/subset-font.mjs. Do not edit.
 * font    Zen Kaku Gothic New 400;500;700
 * chars   141 (3697ab85e1e494ee)
 *
 * pattern.html の文字だけを含む部分集合。描画時に外部へ取りに行かないよう同梱する。
 * 版の文字を変えたら取り直すこと — 忘れると足りない字が豆腐になる。
 * その取り忘れは pattern-entries.test.ts が上の指紋で検出する。
 */

@font-face {
  font-family: 'Zen Kaku Gothic New';
  font-style: normal;
  font-weight: 400;
  font-display: block;
  src: url(./font-0.woff2) format('woff2');
  unicode-range: U+2d, U+2f-34, U+37, U+41, U+47, U+49, U+4b, U+4f-50, U+53-54, U+57, U+61, U+65, U+68-69, U+6b-6c, U+6f, U+72-75, U+79-7a, U+2014, U+2192, U+3002, U+3044, U+304b-304c, U+304f-3050, U+3057-305a, U+3066-306b, U+306e-3070, U+3078-3079, U+307f, U+3082, U+3089-308b, U+3092, U+3099, U+30ad-30ae, U+30b1-30b2, U+30b7-30ba, U+30f3, U+30fb-30fc, U+4e00, U+4e0a-4e0b, U+4e0e, U+4ed6, U+4ed8, U+4f1a, U+4f8b, U+4fdd, U+4fe1, U+5024, U+5148, U+5165, U+518d, U+521d, U+5225, U+5247, U+529f, U+5370, U+5374, U+53d6-53d7, U+540c, U+56de, U+5931, U+5b58, U+5b9a, U+5b9f, U+5ba2, U+5e8f, U+5f97, U+5fdc, U+6210, U+623b, U+6255, U+627f, U+6392, U+652f, U+6557, U+6587, U+6642, U+672a, U+679c, U+67b6, U+691c, U+6c42, U+6c7a, U+6ce8, U+6e08, U+7167, U+753b, U+767b, U+77e2, U+78ba, U+793a, U+7a7a, U+7b54, U+7ba1, U+7d22, U+7d50, U+7fa9, U+884c, U+8868, U+88c5, U+8907, U+8981, U+898f, U+8a66, U+8a8d, U+8cfc, U+8fd4, U+9001, U+9014, U+91cd, U+9332, U+9593, U+9632, U+9762, U+9806, U+9867, U+ff08-ff09;
}
@font-face {
  font-family: 'Zen Kaku Gothic New';
  font-style: normal;
  font-weight: 500;
  font-display: block;
  src: url(./font-1.woff2) format('woff2');
  unicode-range: U+2d, U+2f-34, U+37, U+41, U+47, U+49, U+4b, U+4f-50, U+53-54, U+57, U+61, U+65, U+68-69, U+6b-6c, U+6f, U+72-75, U+79-7a, U+2014, U+2192, U+3002, U+3044, U+304b-304c, U+304f-3050, U+3057-305a, U+3066-306b, U+306e-3070, U+3078-3079, U+307f, U+3082, U+3089-308b, U+3092, U+3099, U+30ad-30ae, U+30b1-30b2, U+30b7-30ba, U+30f3, U+30fb-30fc, U+4e00, U+4e0a-4e0b, U+4e0e, U+4ed6, U+4ed8, U+4f1a, U+4f8b, U+4fdd, U+4fe1, U+5024, U+5148, U+5165, U+518d, U+521d, U+5225, U+5247, U+529f, U+5370, U+5374, U+53d6-53d7, U+540c, U+56de, U+5931, U+5b58, U+5b9a, U+5b9f, U+5ba2, U+5e8f, U+5f97, U+5fdc, U+6210, U+623b, U+6255, U+627f, U+6392, U+652f, U+6557, U+6587, U+6642, U+672a, U+679c, U+67b6, U+691c, U+6c42, U+6c7a, U+6ce8, U+6e08, U+7167, U+753b, U+767b, U+77e2, U+78ba, U+793a, U+7a7a, U+7b54, U+7ba1, U+7d22, U+7d50, U+7fa9, U+884c, U+8868, U+88c5, U+8907, U+8981, U+898f, U+8a66, U+8a8d, U+8cfc, U+8fd4, U+9001, U+9014, U+91cd, U+9332, U+9593, U+9632, U+9762, U+9806, U+9867, U+ff08-ff09;
}
@font-face {
  font-family: 'Zen Kaku Gothic New';
  font-style: normal;
  font-weight: 700;
  font-display: block;
  src: url(./font-2.woff2) format('woff2');
  unicode-range: U+2d, U+2f-34, U+37, U+41, U+47, U+49, U+4b, U+4f-50, U+53-54, U+57, U+61, U+65, U+68-69, U+6b-6c, U+6f, U+72-75, U+79-7a, U+2014, U+2192, U+3002, U+3044, U+304b-304c, U+304f-3050, U+3057-305a, U+3066-306b, U+306e-3070, U+3078-3079, U+307f, U+3082, U+3089-308b, U+3092, U+3099, U+30ad-30ae, U+30b1-30b2, U+30b7-30ba, U+30f3, U+30fb-30fc, U+4e00, U+4e0a-4e0b, U+4e0e, U+4ed6, U+4ed8, U+4f1a, U+4f8b, U+4fdd, U+4fe1, U+5024, U+5148, U+5165, U+518d, U+521d, U+5225, U+5247, U+529f, U+5370, U+5374, U+53d6-53d7, U+540c, U+56de, U+5931, U+5b58, U+5b9a, U+5b9f, U+5ba2, U+5e8f, U+5f97, U+5fdc, U+6210, U+623b, U+6255, U+627f, U+6392, U+652f, U+6557, U+6587, U+6642, U+672a, U+679c, U+67b6, U+691c, U+6c42, U+6c7a, U+6ce8, U+6e08, U+7167, U+753b, U+767b, U+77e2, U+78ba, U+793a, U+7a7a, U+7b54, U+7ba1, U+7d22, U+7d50, U+7fa9, U+884c, U+8868, U+88c5, U+8907, U+8981, U+898f, U+8a66, U+8a8d, U+8cfc, U+8fd4, U+9001, U+9014, U+91cd, U+9332, U+9593, U+9632, U+9762, U+9806, U+9867, U+ff08-ff09;
}

Notes

視覚的な問い

決済リクエストの重複をどこで検出し、初回と再送でどの順に応答するか。

構造

参加者ごとに縦のライフラインを置き、時間を上から下へ進める。実線の要求が右へ進み、破線の応答が左へ戻る。キー保管の照会結果を受けて、未登録なら決済GWへ与信要求と保存済み結果の記録を行い、同一キーが登録済みなら保存結果を購入画面へ返す。

キーの照会を外部与信の前に置くことで、重複再送が新しい与信処理へ進まない境界を明示する。工程の節点を列挙するprocess-flowや、システム間を概観するsystem-landscape mapと異なり、このシーケンス図は参加者間のメッセージ順と条件分岐を示す。架空の要求例で、実装には同時要求の排他・失敗時の再試行規則が別途必要となる。