miive プロダクトブログ

miiveのプロダクトチームのブログです。

カード決済の突合設計:BASE1 / BASE2 をどう突合させるか。〜請求と返金のマッチングの裏側〜

あいさつ

こんにちは。miiveのmineです。カード決済のお金にかかわるところを開発しています。

今回は半年以上関わってきたBASE1(仮売上)とBASE2(請求)の突合についてお話ししていこうと思います。

業務用語 決済用語 意味
BASE1 Authorization / Void / Cancel 与信
BASE2 Capture / Refund 売上確定

カード決済において仮売上と請求は切っても切れない関係ですが、突合するのは一苦労です。

カード決済の業務で、
「仮売上」と「請求」の突合しようとした場合、
だいたいの人は最初にこう思います。

仮売上と請求って、IDでくっつければ終わりじゃないの?

私も最初はそう思っていました。そうだったら本当に良かったです。。。

しかし、実運用ですぐにわかります。

IDだけではデータは合いません。時には合います。これ本当に曲者です。

完全な整合性が取れない以上、信用してはいけません。

以下、一例で他にもいろいろあります

  • IDが違う。そもそも空白。
  • 日付がズレる
  • 加盟店IDが違う

「合わない」のが普通、という世界でした。

今回はBASE1の時点で売上と返品が発生した場合、BASE2で同一の決済に対して徴収と返金が再度処理されないようにするためBASE1と突合して、重複処理をさせないようにする実装をした経験からくるお話です。


売上・返金と BASE1 / BASE2 の関係

場面 業務用語 決済用語 BASE1 / BASE2 との関係 やさしい説明
カードが使えるか確認 仮売上 Authorization BASE1 「このカードで払えますか?」を確認するだけの処理。この時点ではまだ実際のお金は動きません。
カードのユーザー視点ではここでお金が動いているように見えます。
決済システムでもお金が動いているように処理しますが、現実では動きません。
売上前に取り消す 売上取消 Void / Cancel BASE1 「やっぱり(仮売上を)やめます」を伝える処理。この時点ではまだ実際のお金は動きません。
カードのユーザー視点ではここでお金が動いているように見えます。
決済システムでもお金が動いているように処理しますが、現実では動きません。
売上を確定する 売上確定 Capture BASE2 実際にカード会社へ請求がいき、本当に支払いが確定する処理です。
お客様視点では仮売上でお金は動いていますので、金額変更がなければカード会社側では何もしないです。
支払い後に戻す 返金 Refund BASE2 「すでに払ったお金(売上確定)を返す」処理です。本当に返金が確定する処理です。
お客様視点では売上取消でお金は動いています。

返金は売上確定とほぼワンセットなので、返金の場合は売上確定1000円、返金1000円とデータが連携されます。日時も順番もバラバラなのでBASE1とBASE2で二重処理しないためにもBASE1との突合が必要になります。


突合とは「一致させる」作業ではない

この業務を続けていく中で、
私は突合を次のように定義するようになりました。

突合とは、
フィルターを一つずつ追加していく作業である。

一致しているものを探す、のではなく、

  • 1つ1つの条件を積み上げる
  • 条件は厳しくし、怪しいと思ったら突合させません。
  • 突合対象は正確を期し、誤突合は発生させてはいけません。
  • 誤突合するくらいなら通してしまいましょう。あとで調査します。

そんな設計にしています。

最初のうちはよく突合条件からこぼれ落ちてそのまま処理されてしまう。

調査は一苦労。いろいろな角度から目で見てマッチング。フィルターとして有用なら追加します。


BASE1 と BASE2 はそもそも別物

BASE1(仮売上)

  • 与信結果
  • 金額は仮
  • 実売上ではない
  • キャンセルされることもある

BASE2(請求)

  • 売上確定
  • 実際に請求される金額
  • 会計に乗るデータ

BASE1とBASE2は
「同じ取引を表現しているが、同じデータではない」

ここを混ぜると設計が破綻します。

突合に使われるものとしては主に以下のような情報があります。

  • 契約番号 (これは信用できるがこれだけでは突合できないです)
  • 承認番号
  • 取引ID
  • 金額
  • 日時
  • 加盟店情報

 


図解:突合は「ふるい」にかける作業

誤解されがちな突合

ID一発で一致!

現実はこうです。

フィルターに検知されたデータのみ突合。

これでも漏れる時は漏れますので、日々研鑽を心がけます。


最初は「厳しく」突合します

実装初期、私は意図的に条件を厳しくしました。

最初に使っていた条件

  • 承認番号
  • 取引ID
  • 契約番号
  • 金額
  • 日時
  • 45日を超えない。※これは仕様で45日を超えてBASE2が来ない取引は不成立として候補から除外するためです

誤突合は最悪
未突合は調査できる

「絶対に間違わない突合」を最優先しました。

最初は突合できないことが多かったが、日々の観察と調査からフィルター②、フィルター③などを追加していき狙い通りの突合ができるようになっていきました。日々改良を施して少しずつ100%に近づけていきます。100%にはなりませんが観察対象(マッチング失敗データ)が日々減っていくのは嬉しかったです。


実運用では必ずズレる

  • 承認番号が違う
  • 取引IDが違う
  • 日付がずれる
  • 数日後にくる
  • 加盟店IDが違う

BASE2 は「到着即処理」が鉄則

BASE2 到着
   ↓
即突合
   ↓
候補抽出
   ↓
保存

放置すると:

  • 未請求
  • 二重請求
  • 問い合わせ地獄

おわりに

システムは、
正しく動くより、
誤らないことの方が重要な場面があります。

カード決済は、その典型だと思います。

数字の誤り、誤情報はお金を扱う場面ではひとつのミスでも致命的になります。

安直な突合はやめましょう。

この記事がこれから決済に関わる誰かの設計のヒントになれば幸いです。

we are hiring!

miiveはWe Work 新宿を拠点にしており、気軽に仕事や働き方を語れる「miive bar」を定期的に開催中です。
miiveについて気になった方はぜひご連絡ください!

miive.notion.site