#3」が開催されました。第3回となる今回のテーマは「モバイル決済の裏側」。急速に成長するモバイル決済分野でサービスを展開する企業が一堂に会し、自社サービスの仕組みや技術スタックなど、知られざる裏側を語ります。」に登壇したのは、株式会社メルペイのsusho氏。今年の6月にサービスが開始したばかりのメルペイのサーバーサイドの特徴と工夫について語ります。提供:PayPay株式会社スピーカーsusho0220株式会社メルペイ静的MPM決済を支える技術susho氏:こんばんは。「静的MPM決済を支える技術」ということでsushoが発表させていただきます。社内ではsushoと呼ばれているので、ここでもそうさせていただいております。Twitterは@susho0220でやっています。Paymentチームに所属しています。Go歴は4年ぐらいです。JAPANに在籍していまして、そこでオブジェクトストレージ「Dragon」の開発に従事していました。今日のアジェンダです。最初に「静的MPMとは」というお話をさせていただいて、そのあとは静的MPMを使ったマイクロサービスアーキテクチャについてお話します。最後は、マイクロサービスアーキテクチャで実装する上での不整合対策についてお話できればと思います。「静的MPMとは」です。静的MPMとは、店舗で紙などに印刷された固定のQRコードを提示して、それをお客様が読み込んで決済するというものです。メリットは、店舗側はQRコードを配置するだけで導入可能なので、CPMなどの他のQRコード決済の仕組みと違い、POSなどが不要なので導入コストが非常に安いです。考えれるデメリットとしては、QRコードが改ざんされる恐れがあります。これは昔の話ですが、改ざん防止のために固定のQRコードをガラスに貼ったり、特殊なステッカーに印刷したり、決済時に強制的に音を出させたり、結果を店舗のメールアドレスに通知することで改ざん防止しています。拡大していっています。メルペイの静的MPMの仕様ですが、JCBやVisa、Mastercardなどの国際ブランド6社からなる技術団体「EMVCo」というものがあり、そこで策定された共通規格「EMV」を採用しています。QRコードのエンコードとデコードでは自社で開発したOSSのライブラリ「go-emv-code」というものを使っています。続いて、この静的MPMのマイクロサービスアーキテクチャについて説明したいと思います。概要になってしまいますが、順を追って説明をしていきたいと思います。メルペイでは各マイクロサービスがGCPのGKE上に構成されています。GatewayというAPIゲートウェイにHTTP+JSONやHTTP+ProtocolBuffersのリクエストがきて、そこで内部通信に使っているgRPCへのプロトコル変換やルーティング、認証を行っています。Serviceというマイクロサービスがあり、ここで認証トークンを生成しています。Serviceとバックグラウンドで通信をして、トークンの鍵を取得しています。APIにリクエストが飛んできます。ここはいわゆるBFFの機能を担っています。Serviceという、今回主に実装したマイクロサービスにリクエストが飛んできます。ここではまずQRコードの解釈を行います。Serviceにリクエストが投げられます。Serviceにリクエストを飛ばして通知を行います。こんな感じになっています。決済シーケンスについて続いて決済シーケンスについて、もう少し踏み込んだ部分を説明したいと思います。APIにQRコードと一緒にセッション生成リクエストが投げられます。ServiceがQRコードの解釈・店舗情報の取得・セッショントークンの生成を行います。セッショントークンについては後述します。行い、お客様のアプリに完了画面が表示されるというシーケンスになっています。Serviceについてどんな機能があるのかを説明します。静的MPM決済のドメインに関するマイクロサービスでQRコード解釈では、go-emv-codeを使っています。アプリでQRコードを解釈することも考えたんですが、今後のさまざまなQRコードの仕様に対応する必要があり、拡張性を高くしたかったのでバックエンド側で処理をしています。ここで出てきたセッショントークンなんですが、アプリでQRコードを読み取ったあとに一定期間のみ決済可能にする仕組みです。これは何のために実装したかというと、お客様がQRコードを読み取ってそのあと画面を一定期間放置して、そのあとに間違って購入ボタンを押してしまった場合にも決済ができてしまうので、一定期間放置されたセッションは弾くような実装をしています。決済処理ですが、いろいろなマイクロサービスでやり取りをして、静的MPM決済のドメインに沿った各処理を実行しています。ここの決済処理の設計をミスすると容易に不整合が発生してしまうので難しいです。先月、弊社のエンジニアが「マイクロサービスにおける決済トランザクション管理」というブログを出していたので、読んでいない人は読んでみてください。難しいということがあったので、それについてざっくりと説明したいと思います。不整合対策をする上で、僕らが考えているキーポイントです。repairが大事だと考えています。冪等性に関しては、クライアントは同じリクエストを繰り返し呼ぶことができ、かつ同じレスポンスが返ってくるという状態です。Keyという、各々が発行したUUIDをリクエストに付与しています。通信先のマイクロサービスやネットワークに一時的な障害があった場合、クライアントは同じリクエストをリトライすることで不整合をオンデマンドに修復できます。タイムアウトとリトライを使ってやっています。そのためにGoのgRPCのInterceptorのライブラリであるgrpc_retryを利用しています。repairでリトライしても修復できなかった場合に、非同期でマイクロサービス間の最終的な状態をチェックして、仮に不整合が発生した場合はあるべき状態に修復します。Pub/Subなどを使ってイベント駆動な設計にして、よりスケールするように修正する予定です。repairについてざっくりと説明します。repairについてです。Serviceにリクエストをします。Keyを作って一旦データベースにトランザクションとともにログとして書き込みます。このときはステータスをinitialとしています。KeyのYYYを付与して投げます。Keyを取得し、同じようにリトライをすることで不整合を解消できます。Serviceに確認しにいきます。仮にAuthorizedだった場合、決済の取り消しリクエストを実行して、対象のトランザクションをキャンセルします。FoundだったりAuthorizedではないステータスだった場合は、そのままトランザクションを破棄します。現状の課題と今後について現状の課題です。これらの各機能をマイクロサービスそれぞれのアプリケーションコードに実装しなければならないということと、通信元や通信先のネットワーク遅延や分断状態を再現してテストをするのがとても難しいです。iptablesで疑似的にパケット遅延を発生させたりしてテストをすることはできるんですが、けっこう大変で、etcdという分散キーバリューストアでGoでごりごりテストをしているんですが、なかなか大変です。これから試してみたいことは、Envoyを使ってサービスメッシュの導入をしていきたいと考えています。Injectionという機能があるので、それを使ってもう少し信頼性が高く開発しやすい基盤を使っていきたいと思います。go-emv-codeを使うとEMV規格のQRコードのエンコードやデコードができるので、使っていただけるとありがたいです。サービスメッシュの登場で、マイクロサービス間の不整合対策の実装やテストがやりやすくなっていきそうな気がしているので、導入して試していきたいと思っています。ご清聴ありがとうございました。JAPANに関する記事をまとめています。JAPANに関する新着記事が公開された際に、通知を受け取ることができます。