2024.12.19
システムの穴を運用でカバーしようとしてミス多発… バグが大量発生、決算が合わない状態から業務効率化を実現するまで
静的MPM決済を支える技術(全1記事)
提供:PayPay株式会社
リンクをコピー
記事をブックマーク
susho氏:こんばんは。「静的MPM決済を支える技術」ということでsushoが発表させていただきます。
最初に自己紹介です。
社内ではsushoと呼ばれているので、ここでもそうさせていただいております。Twitterは@susho0220でやっています。バックエンドエンジニアで、メルペイのCode Paymentチームに所属しています。Go歴は4年ぐらいです。僕も2018年までYahoo! JAPANに在籍していまして、そこでオブジェクトストレージ「Dragon」の開発に従事していました。
今日のアジェンダです。
最初に「静的MPMとは」というお話をさせていただいて、そのあとは静的MPMを使ったマイクロサービスアーキテクチャについてお話します。最後は、マイクロサービスアーキテクチャで実装する上での不整合対策についてお話できればと思います。
まず「静的MPMとは」です。
静的MPMとは、店舗で紙などに印刷された固定のQRコードを提示して、それをお客様が読み込んで決済するというものです。メリットは、店舗側はQRコードを配置するだけで導入可能なので、CPMなどの他のQRコード決済の仕組みと違い、POSなどが不要なので導入コストが非常に安いです。
考えれるデメリットとしては、QRコードが改ざんされる恐れがあります。これは昔の話ですが、改ざん防止のために固定のQRコードをガラスに貼ったり、特殊なステッカーに印刷したり、決済時に強制的に音を出させたり、結果を店舗のメールアドレスに通知することで改ざん防止しています。
6月27日に「メルペイ」のお客さま読み取り式コード決済機能をリリースしました(プレスリリース)。現在順次利用店舗を拡大していっています。
メルペイの静的MPMの仕様ですが、JCBやVisa、Mastercardなどの国際ブランド6社からなる技術団体「EMVCo」というものがあり、そこで策定された共通規格「EMV」を採用しています。
また、QRコードのエンコードとデコードでは自社で開発したOSSのライブラリ「go-emv-code」というものを使っています。
続いて、この静的MPMのマイクロサービスアーキテクチャについて説明したいと思います。概要になってしまいますが、順を追って説明をしていきたいと思います。
メルペイでは各マイクロサービスがGCPのGKE上に構成されています。
これは静的MPMのざっくりしたシーケンスですが、まずはGoogle Cloud Load BalancerからMerpay GatewayというAPIゲートウェイにHTTP+JSONやHTTP+ProtocolBuffersのリクエストがきて、そこで内部通信に使っているgRPCへのプロトコル変換やルーティング、認証を行っています。
この認証にはAuthority Serviceというマイクロサービスがあり、ここで認証トークンを生成しています。この認証トークンはすべてのマイクロサービスが検証をする必要があり、各マイクロサービスはAuthority Serviceとバックグラウンドで通信をして、トークンの鍵を取得しています。
その他の処理が行われたあと、Merpay APIにリクエストが飛んできます。ここはいわゆるBFFの機能を担っています。
そしてMerpay APIからStaticMPM Serviceという、今回主に実装したマイクロサービスにリクエストが飛んできます。ここではまずQRコードの解釈を行います。QRコードの中に入っている店舗情報のキーになるIDを取ってきて、Partner Serviceから店舗情報を取得し、実際の決済処理のために決済共通の処理を行うTransaction Serviceにリクエストを投げ、決済基盤であるPayment Serviceにリクエストが投げられます。
これが成功したら、通知処理を担うNotification Serviceにリクエストを飛ばして通知を行います。だいぶざっくりですが、こんな感じになっています。
続いて決済シーケンスについて、もう少し踏み込んだ部分を説明したいと思います。最初のメルカリアプリ内でQRコードを読み取り、Mercari AppからMerpay APIにQRコードと一緒にセッション生成リクエストが投げられます。
そこからStaticMPM Serviceにリクエストがきて、StaticMPM ServiceがQRコードの解釈・店舗情報の取得・セッショントークンの生成を行います。セッショントークンについては後述します。
そこから店舗情報とセッショントークンを返し、Mercari App内で購入画面が表示され、金額入力、購入ボタンを押し、また決済リクエストが飛んできて、StaticMPM Serviceではセッショントークンの検証と決済処理、通知処理を行い、お客様のアプリに完了画面が表示されるというシーケンスになっています。
StaticMPM Serviceについてどんな機能があるのかを説明します。
静的MPM決済のドメインに関するマイクロサービスでQRコード解釈では、go-emv-codeを使っています。アプリでQRコードを解釈することも考えたんですが、今後のさまざまなQRコードの仕様に対応する必要があり、拡張性を高くしたかったのでバックエンド側で処理をしています。
ここで出てきたセッショントークンなんですが、アプリでQRコードを読み取ったあとに一定期間のみ決済可能にする仕組みです。これは何のために実装したかというと、お客様がQRコードを読み取ってそのあと画面を一定期間放置して、そのあとに間違って購入ボタンを押してしまった場合にも決済ができてしまうので、一定期間放置されたセッションは弾くような実装をしています。
決済処理ですが、いろいろなマイクロサービスでやり取りをして、静的MPM決済のドメインに沿った各処理を実行しています。ここの決済処理の設計をミスすると容易に不整合が発生してしまうので難しいです。先月、弊社のエンジニアが「マイクロサービスにおける決済トランザクション管理」というブログを出していたので、読んでいない人は読んでみてください。
不整合対策が難しいということがあったので、それについてざっくりと説明したいと思います。不整合対策をする上で、僕らが考えているキーポイントです。
まず冪等性、Write repair、Asynchronous repairが大事だと考えています。冪等性に関しては、クライアントは同じリクエストを繰り返し呼ぶことができ、かつ同じレスポンスが返ってくるという状態です。
メルペイでは、クライアントがIdempotency Keyという、各々が発行したUUIDをリクエストに付与しています。
続いてWrite repairです。通信先のマイクロサービスやネットワークに一時的な障害があった場合、クライアントは同じリクエストをリトライすることで不整合をオンデマンドに修復できます。タイムアウトとリトライを使ってやっています。
そのためにGoのgRPCのInterceptorのライブラリであるgrpc_retryを利用しています。
Asynchronous repairですが、Write repairでリトライしても修復できなかった場合に、非同期でマイクロサービス間の最終的な状態をチェックして、仮に不整合が発生した場合はあるべき状態に修復します。今はバッチによる定期実行をしていますが、今後の予定としてはCloud Pub/Subなどを使ってイベント駆動な設計にして、よりスケールするように修正する予定です。
では、ここで新たにでてきたWrite repairとAsynchronous repairについてざっくりと説明します。
まずはWrite repairについてです。StaticMPM Serviceが決済リクエストを投げるときに、Idempotency Key XXXというものを付与してTransaction Serviceにリクエストをします。Transaction Serviceは、そこからYYYというIdempotency Keyを作って一旦データベースにトランザクションとともにログとして書き込みます。このときはステータスをinitialとしています。
そこから決済リクエストをPayment Serviceに投げて、このときにIdempotency KeyのYYYを付与して投げます。
ここでPayment Serviceが高負荷であったり、ネットワークの分断があったりして決済がうまくいかなかったと仮定した場合、クライアントがタイムアウトを検知して、同じIdempotency Keyでリトライして、Transaction Serviceがログとして書き込んだIdempotency Keyを取得し、同じようにリトライをすることで不整合を解消できます。
続いてAsynchronous repairです。
ここは簡単で、ステータスが一定時間経過してもinitialなままだったトランザクションをデータベースが定期的にスキャンして、その対象の状態をPayment Serviceに確認しにいきます。仮にAuthorizedだった場合、決済の取り消しリクエストを実行して、対象のトランザクションをキャンセルします。そしてNot FoundだったりAuthorizedではないステータスだった場合は、そのままトランザクションを破棄します。
現状の課題です。これらの各機能をマイクロサービスそれぞれのアプリケーションコードに実装しなければならないということと、通信元や通信先のネットワーク遅延や分断状態を再現してテストをするのがとても難しいです。例えばiptablesで疑似的にパケット遅延を発生させたりしてテストをすることはできるんですが、けっこう大変で、etcdという分散キーバリューストアでGoでごりごりテストをしているんですが、なかなか大変です。
これから試してみたいことは、Envoyを使ってサービスメッシュの導入をしていきたいと考えています。これにはタイムアウトやリトライのテストをしやすくするためのFault Injectionという機能があるので、それを使ってもう少し信頼性が高く開発しやすい基盤を使っていきたいと思います。
まとめです。go-emv-codeを使うとEMV規格のQRコードのエンコードやデコードができるので、使っていただけるとありがたいです。サービスメッシュの登場で、マイクロサービス間の不整合対策の実装やテストがやりやすくなっていきそうな気がしているので、導入して試していきたいと思っています。
以上です。ご清聴ありがとうございました。
(会場拍手)
PayPay株式会社
関連タグ:
2024.12.20
日本の約10倍がん患者が殺到し、病院はキャパオーバー ジャパンハートが描く医療の未来と、カンボジアに新病院を作る理由
2024.12.19
12万通りの「資格の組み合わせ」の中で厳選された60の項目 532の資格を持つ林雄次氏の新刊『資格のかけ算』の見所
2024.12.16
32歳で成績最下位から1年でトップ営業になれた理由 売るテクニックよりも大事な「あり方」
2023.03.21
民間宇宙開発で高まる「飛行機とロケットの衝突」の危機...どうやって回避する?
PR | 2024.12.20
モンスター化したExcelが、ある日突然崩壊 昭和のガス工事会社を生まれ変わらせた、起死回生のノーコード活用術
2024.12.12
会議で発言しやすくなる「心理的安全性」を高めるには ファシリテーションがうまい人の3つの条件
2024.12.18
「社長以外みんな儲かる給与設計」にした理由 経営者たちが語る、優秀な人材集め・会社を発展させるためのヒント
2024.12.17
面接で「後輩を指導できなさそう」と思われる人の伝え方 歳を重ねるほど重視される経験の「ノウハウ化」
2024.12.13
ファシリテーターは「しゃべらないほうがいい」理由 入山章栄氏が語る、心理的安全性の高い場を作るポイント
2024.12.10
メールのラリー回数でわかる「評価されない人」の特徴 職場での評価を下げる行動5選
Climbers Startup JAPAN EXPO 2024 - 秋 -
2024.11.20 - 2024.11.21
『主体的なキャリア形成』を考える~資格のかけ算について〜
2024.12.07 - 2024.12.07
Startup CTO of the year 2024
2024.11.19 - 2024.11.19
社員の力を引き出す経営戦略〜ひとり一人が自ら成長する組織づくり〜
2024.11.20 - 2024.11.20
「確率思考」で未来を見通す 事業を成功に導く意思決定 ~エビデンス・ベースド・マーケティング思考の調査分析で事業に有効な予測手法とは~
2024.11.05 - 2024.11.05