Slide 1

Slide 1 text

@hiraku iD決済を支える技術(server side) ※「iD」は株式会社NTTドコモの商標です

Slide 2

Slide 2 text

@hiraku (中野 拓) ● 2015年12月 メルカリにPHPエンジニアとしてJoin ○ Composerを速くする趣味 ● 2018年2月 メルペイに異動 ○ 最初はPHPコードの改修をやってた ○ 4月~ bank-service(銀行接続) ○ 9月~ nfc-serviceほぼ専属に ● 2019年2月 iD決済リリース!!

Slide 3

Slide 3 text

リリースした今なら言える ネタばらし色々

Slide 4

Slide 4 text

目次 1. iD決済(メルペイ電子マネー) 2. システム構成 3. フレームワーク談義 4. microservicesのつらいところ

Slide 5

Slide 5 text

iD決済(メルペイ電子マネー)

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

● メルカリの売上金を使って買い物できる ● iOS→Apple Pay ● Android→おサイフケータイ ○ iDがauのスマホでも使えるという熱々 ポイント ● バックエンド側の開発がうちのチーム

Slide 8

Slide 8 text

NFC決済の特徴 ● Pros ○ 全国80万箇所+で使える!(iDとの提携) ○ 決済体験のスムーズさ ○ Apple Payを経由するとSuicaチャージやアプリ内決済にも ○ 3大キャリア x iOS/Android 全部使える ● Cons ○ 加盟店側にNFCリーダーが必要 ○ 加盟店側に決済手数料が… (※コード払いとの比較) ○ スマホがFeliCa対応でないと使えない

Slide 9

Slide 9 text

NFC決済を使うまでの道のり 1. Virtual Cardを発行する a. クレカではなくプリペイドカードの扱い b. 発行自体は三井住友カード社のシステムで行う 2. Device-PANを発行して端末のチップに書き込む 1. レジ端末にピッとかざすと、店舗側のネットワークから経由して メルペイに通信が来る 2. 残高が足りていればOKを返して、決済が成功する

Slide 10

Slide 10 text

電子マネーのタイプ ● サーバー管理型プリペイドのバーチャルカード(物理板はない) ● メルペイ側で全てのvalue(売上金 or ポイント)を管理 ○ 決済ごとにメルペイに通信して、相当額を「チャージ」して即座 に使っている ○ 自動販売機やガソリンスタンドなど、店舗の端末がオフラインだ と使えない ○ 逆にiPhone/Androidは機内モードやオフラインでもOK

Slide 11

Slide 11 text

システム構成

Slide 12

Slide 12 text

"メルペイがmicroservicesを採用し たのは、他に選択肢がなかったから" by @kazegusuri (merpay architect)

Slide 13

Slide 13 text

メルペイのシステムの前提 ● 多くのシステムを同時に作る必要があった ○ コード払い ○ あと払い ○ メルカリ内決済 ...etc ● microservicesを採用して、各チームで試行錯誤するしかなかった →NFC決済システムも、専用serviceとして作成することに

Slide 14

Slide 14 text

NFC決済を実現するために必要だったもの ● 主な機能はSMCC社のシステムで実現できた ● 登録系 1. メルカリ会員 ⇔ カード の管理 2. 端末プロビジョニングに必要なAPIをproxyして、ユーザー認証を 正しく実装する ● 決済利用系 1. SMCC社から来る承認リクエストを受けて、即座に結果を返す

Slide 15

Slide 15 text

nfc-service merpay-gateway registration / provisioning nfc-serviceが不要な一部機能の実装 関係するmicroservices merpay-gateway nfc-api merpay-api payment, balance, etc charge (決済利用) SMCC (カード発行& 管理) POS casher registration (登録) user_id ⇔ cardのDB保持 リクエストの翻訳 アクセス元の認証 mercari-api SMS認証 電話番号参照

Slide 16

Slide 16 text

nfc-serviceの中身 DB (Cloud Spanner) Kubernetes ● コンテナイメージは一種類、Goのビルド結果が入ってる ○ grpc-server + Pub/Subのsubscriber ○ batch ● k8s Deployment ... grpc-server + subscriber ○ Autoscalerも有効にしてある ● k8s CronJob ... batch ● k8s ConfigMap ... 他serviceのアドレスなどの設定 ● k8s Secret ... 秘匿性の高い鍵など ● DataDogでメトリクス収集、監視 Cloud Pub/Sub

Slide 17

Slide 17 text

nfc-serviceのk8s.yaml $ grep 'kind:' k8s.yaml kind: Deployment kind: ConfigMap kind: Service kind: CronJob kind: CronJob kind: CronJob kind: CronJob kind: CronJob kind: CronJob kind: CronJob kind: CronJob kind: CronJob

Slide 18

Slide 18 text

バッチ…

Slide 19

Slide 19 text

バッチ度の高いkubernetesアプリケーション ● カードのバッチ発行 ○ リアルタイムには発行済のカードから割り当てるだけにする ● 発行依頼→発行→取り込み (全部バッチ…) ● 売上の日次確定処理 ● microservice同士の不整合の検知と修復batch ● etc... ● etc... ● でも何とかなってるのでKubernetesすごい

Slide 20

Slide 20 text

デプロイの関係 ● 「バッチが動いてるときにデプロイして良いんだっけ?」 →CronJobはPodを生成して動きはじめるので、Deploymentを上書 きしても支障はない ● その他のデプロイ時の細かい問題はSpinnakerが吸収している ○ ConfigMapに自動でversion切るとか

Slide 21

Slide 21 text

フレームワーク談義

Slide 22

Slide 22 text

"フレームワークはプロジェクトの初 期の段階では便利ですが、フレーム ワークに付加された複雑さにより 長期の保守が難しくなります" プログラミング言語Go P223より

Slide 23

Slide 23 text

gRPCサーバーを作る必要があったので ● google.golang.org/grpc を素朴に使って実装していく ● interceptorを使って抽象化 ○ Webフレームワークだとmiddlewareって呼ばれるような機構 ○ 内製interceptorがいっぱいある ○ 認証 ○ ログ ○ DataDog ● ロガーは zap が実質標準

Slide 24

Slide 24 text

ソースツリー雰囲気 ● cmd/server/main.go ● grpc/server.go ... gRPCサーバーのinterceptor組み立て ● grpc/charge/ ... 決済系のgRPCサービスコード ● grpc/registration/ ... 登録系のgRPCサービスコード ● usecase/ ... ドメインロジック本体色々 ● model/ ... Entity. DBに記録される構造 ● repository/ ... DB操作色々

Slide 25

Slide 25 text

困ったこと ● grpc-serverは割と作法が固まってて悩みにくかった ○ エラーコードがHTTPと違うのには未だ慣れないが… ● batchとpubsubのsubscriberは、自己流… ● batch系とserver系でコードの重複があるけど、うまく抽象化できて いない

Slide 26

Slide 26 text

microservicesのつらいところ

Slide 27

Slide 27 text

他serviceとの整合性

Slide 28

Slide 28 text

こういうタイムアウトが困る nfc payment 決済処理して nfc payment ...返事がない 打ち切ろう 実は成功して ました

Slide 29

Slide 29 text

不整合はどこにでも起きうる ● nfcとpayment ○ 「決済失敗したって返したけど、実は成功してました」 →クライアントが失敗を受けてリトライすると、 二重決済になる! ● nfcとSMCCシステム ● etc... ● microservicesはDBを共有しない = DBトランザクションが使えない

Slide 30

Slide 30 text

こうやって解決 nfc payment 決済処理して nfc payment ...返事がない 打ち切ろう 実は成功して ました 決済指示を 記録 打ち切りを 記録 nfc repairer payment側の最終状態を確認 不整合は取り消しを実行、自動修復

Slide 31

Slide 31 text

いわゆるジャーナリングと冪等性によるリトライ ● 全ての処理は一意なidを振り、なるべく冪等になるように作る ● いつでも気軽にリトライできるようにする ● 不整合は別プロセスが復旧していく ● 泥臭いけど、仕方ない ● これって、一般的なDB製品が備えているトランザクションの基礎技術 そのものだよね…? ● 最終的に問題のない状態へ収束するように作る

Slide 32

Slide 32 text

まとめと総括

Slide 33

Slide 33 text

この一年どうだった? ● 4月になるまでGoもk8sもガッ ツリ開発に使ったことなかった ○ 手探りで進まない無力感 ● チームメンバー、SREや Architectに圧倒的感謝 ● 珉珉六本木店のチャーハン餃子 セット