Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Elixir で決済サービスをつくってみた

enerick
November 30, 2019

Elixir で決済サービスをつくってみた

Developer Boost 2019 の発表資料です

enerick

November 30, 2019
Tweet

Other Decks in Programming

Transcript

  1. Elixirで決済サービスを
 つくってみた Developer Boost 2019 株式会社ミクシィ ID・ペイメント事業部 橋本広⼤ 2019/11/30

  2. 今⽇話すこと つくってみた決済システムについて 6gram サービス紹介 決済システム概観 Elixir でのアプリケーション開発について Elixir について Elixir

    の良いところ・悪いところ 決済サービス開発で便利だったこと
  3. ⾃⼰紹介 橋本広⼤(@enerick) 株式会社ミクシィ ID・ペイメント事業部 2016年4⽉⼊社
 → XFLAG ID の開発・運⽤
 →

    幻のモバイル事業 → 新規の決済系サービス「6gram」や
  社内決済基盤の開発・運⽤を⾏っている
  4. つくってみた決済システムについて

  5. None
  6. 実は最近
 新しい決済サービスを
 リリースしました

  7. 決済システムについて ひとりでもみんなでも使えるウォレットサービス グループに⼊れたお⾦をシェアしたり、インスタントに発⾏したプリペイドカードに
 残⾼を割り付けたりといろんな使い⽅ができる ‣ JCB プリペイドカードを1アカウントで複数枚(!)発⾏できる ‣ Apple Pay/Google

    Pay と連携して QUICPay+ 決済を⾏える ‣ リアルカードも発⾏予定 2019年11⽉にAndroid版をひっそり先⾏リリース ‣ 現在完全招待制 ‣ 読み⽅は「ろくぐらむ」 「6gram」サービス紹介
  8. 決済サービス基礎概念 決済システムについて お⾦の流れには向きがある ⼊⾦:ウォレットへの残⾼チャージ 出⾦:6gramカードを利⽤してウォレットから⽀払い それぞれで求められる役割が異なる

  9. 決済サービス基礎概念 決済システムについて ⼊⾦⽅向でやること ‣ ユーザーが登録するクレジットカードや銀⾏⼝座情報の管理 ‣ 決済リクエストの送信 ‣ 加盟店として、カード会社や銀⾏への売上計上 出⾦⽅向でやること

    ‣ 発⾏したプリペイドカードの管理 ‣ ユーザーの与信管理 ‣ 決済リクエストの受信、許可/拒否応答(オーソリゼーション) ‣ 利⽤された各加盟店から計上される売上に基づいて精算
  10. 決済サービス基礎概念 決済システムについて ⼊⾦⽅向でやること ‣ ユーザーが登録するクレジットカードや銀⾏⼝座情報の管理 ‣ 決済リクエストの送信 ‣ 加盟店として、カード会社や銀⾏への売上計上 出⾦⽅向でやること

    ‣ 発⾏したプリペイドカードの管理 ‣ ユーザーの与信管理 ‣ 決済リクエストの受信、許可/拒否応答(オーソリゼーション) ‣ 利⽤された各加盟店から計上される売上に基づいて精算 6gramでは⼊⾦・出⾦の両⽅向で
 決済ネットワークとの接続システムから
 プリペイドカードのオーソリゼーション・精算システムまで
 すべて内製しました
  11. なんで内製? 決済システムについて ランニングコストや PCI DSS の維持なども含めた運⽤コストを考えると初期 にちょっと頑張って内製できるならそのほうが良いと判断 6gram では可能な限りフルマネージドサービスを利⽤することで少⼈数でも運⽤可能 なサーバーレス

    PCI DSS 対応構成を採⽤している ‣ 既存構成とマッチしそうなパッケージ製品はなさそうだった… ‣ ムリだったら運⽤コストを受け⼊れてパッケージ製品を利⽤すればよい
  12. なんで内製? 決済システムについて 「そもそもパッケージ製品って何をしてくれるんだろう…?
   接続仕様書はどのみち必要らしいし、作ってみたらわかるのでは? 」 ある程度想像はしていたが、⼤変なことも多かった ‣ ⽂字通りの仕様書の⼭(紙のみ・複写禁⽌) ‣ 開発利⽤できる試験環境が無い

    ‣ パッケージを使わないため⼯程マシマシの試験、など ちなみにパッケージを利⽤してもこれらの全てから逃れられるわけではない しかし予定スケジュール通り⼊⾦・出⾦両⽅向の接続が完了 サーバーレス PCI DSS 環境も保たれ結果的に後悔はない…!
  13. 6gram では Elixir をふんだんに利⽤しています 決済システムについて Account アカウントや属性、認証情報の管理 Payment 決済に関連する情報の管理 Gateway

    決済ネットワークとの接続・通信の管理 その他 決済基盤ダッシュボード、6gram 運⽤のための管理ツール
  14. Elixir での Web アプリケーション開発について

  15. Elixir ってどんな⾔語? Erlang VM 上で動作する Erlang/OTP との互換性がある どことなく Ruby inspired

    な⽂法 マクロによる拡張性や Protocol による多相性などを加えている 
 builderscon 2019 での ABEJA の⽯川さんの発表がオススメ ‣ builderscon tokyo 2019 - Elixir: Under the Hood - Qiita
 https://qiita.com/ishikawa@github/items/3d054f3d29920107687f Elixir での Web 開発について
  16. Elixir の良いところ・悪いところ Elixir での Web 開発について Developer Summit 2019 での

    gumi の幾⽥さんの発表がオススメ ‣ 私が愛する Elixir/Erlang の楽しさと⾟さ - Speaker Deck
 https://speakerdeck.com/cooldaemon/erlang-falsele-sisatoxin-sa わかりみ深い… がせっかくなので⾃分の感覚でもいくつか取り上げてみる
  17. Elixir の良いところ Elixir での Web 開発について ‣ Erlang VM の安定性、耐障害性

    ‣ Erlang/OTP のライブラリや資産がそのままつかえる ‣ コア周辺の開発・コミュニティが活発 ‣ 公式ドキュメントがちゃんとしている ‣ パターンマッチ便利 ‣ ⾮同期・並列処理が簡単にかける ‣ 細かい便利機能が⾊々備わっている
  18. 便利なパターンマッチ Elixir での Web 開発について 基本的なパターンマッチ iex> {:ok, result} =

    {:ok, 13} {:ok, 13} iex> result 13 iex> {:ok, result} = {:error, :bad_request} ** (MatchError) no match of right hand side value: {:error, :bad_request} (stdlib) erl_eval.erl:450: :erl_eval.expr/5 (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5 (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3 (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3 (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1 (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4
  19. 便利なパターンマッチ Elixir での Web 開発について 強いパターンマッチ 先頭 2bytes に値の⻑さ、その後ろにその⻑さ bytes

    分の値を持ち、
 その後ろにはまた同じ構造を持つようなバイナリ列をパースしたい 8 "Content1" 4 "Hoge" 2bytes 8bytes
  20. 便利なパターンマッチ Elixir での Web 開発について 強いパターンマッチ 先頭 2bytes に値の⻑さ、その後ろにその⻑さ bytes

    分の値を持ち、
 その後ろにはまた同じ構造を持つようなバイナリ列をパースしたい iex> bin = <<0, 8, "content1", 0, 4, "hoge">> iex> <<len::16, val::binary-size(len), rest::binary>> = bin <<0, 8, 99, 111, 110, 116, 101, 110, 116, 49, 0, 4, 104, 111, 103, 101>> iex> val "content1" iex> rest <<0, 4, 104, 111, 103, 101>>
  21. 便利なパターンマッチ Elixir での Web 開発について 強いパターンマッチ 先頭 2bytes に値の⻑さ、その後ろにその⻑さ bytes

    分の値を持ち、
 その後ろにはまた同じ構造を持つようなバイナリ列をパースしたい iex> bin = <<0, 8, "content1", 0, 4, "hoge">> iex> <<len::16, val::binary-size(len), rest::binary>> = bin <<0, 8, 99, 111, 110, 116, 101, 110, 116, 49, 0, 4, 104, 111, 103, 101>> iex> val "content1" iex> rest <<0, 4, 104, 111, 103, 101>> パターン中で束縛した値をパターン中で使える。つよい
  22. 便利なパターンマッチ Elixir での Web 開発について ちなみに 同様のパターンで「ある値と同じ値」も簡単なパターンで表現できる iex> {n, n}

    = {:ok, :ok} {:ok, :ok} iex> {n, n} = {:ok, 100} ** (MatchError) no match of right hand side value: {:ok, 100} (stdlib) erl_eval.erl:450: :erl_eval.expr/5 (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5 (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3 (iex) lib/iex/evaluator.ex:215: IEx.Evaluator.eval/3 (iex) lib/iex/evaluator.ex:103: IEx.Evaluator.loop/1 (iex) lib/iex/evaluator.ex:27: IEx.Evaluator.init/4
  23. 細かい便利機能たち Elixir での Web 開発について self-contained なリリースファイル⽣成 mix release コマンドでランタイムコミコミのリリースを作成してくれる

    2019年6⽉ にリリースされた v1.9 から標準搭載 ‣ アプリケーションサーバーに Erlang や Elixir のランタイムのインストールの必要 なし リリースファイルのコマンドオプションでスクリプト実⾏も出来るので、バッチ処理 も1バイナリでまかなえる ‣ 6gram の精算処理はこれを利⽤してアプリケーションサーバーと同じイメージを 使って精算バッチを実⾏している
  24. 細かい便利機能たち Elixir での Web 開発について ETS (Erlang Term Storage) で

    in-memory データ保存 ノード内に閉じたデータの保持をしたい場合に外部システムを要さずに
 ETS という OTP 組み込みのデータストレージが利⽤できる ‣ 直接 ETS をつかわなくても Elixir の Registry などからつかうこともできる ‣ 6gram では起動時にデータ読み込みが必要なモジュールで読み込み結果の保持な どにも気軽に利⽤している
  25. 細かい便利機能たち Elixir での Web 開発について 簡単に⾮同期処理、並列処理が書ける Task で気軽に関数の⾮同期実⾏ができる ‣ 結果を気にしないタイプの⾮同期処理でも

    Task.Supervisor を使ってプロセスに紐 付けるのを推奨 ‣ 紐付けておくと、アプリケーションの exit シグナルをトラップして実⾏が中断さ れないようにしたりもできる Flow で気軽にリストなどに対して並列 map などができる ‣ ノード内での並列度のコントロールや処理の待ち合わせなどもできる
  26. Elixir の悪いところ Elixir での Web 開発について ‣ 動的型付けなので動かすと壊れてた・バグってたケースがままある ‣ よく⾔われているが

    Erlang VM の速度⾃体は速くはない ‣ Binary の操作はいろいろ整っている⼀⽅ Bitstring の操作がわりと貧弱 ‣ 公式の SDK やライブラリは無い場合が多く、コミュニティ頼み or ⾃作 ‣ ⼈気ライブラリでも放置気味なものも…
  27. Elixir でよくある動的型付け⾔語っぽいミス Elixir での Web 開発について だいたい Map や Struct

    アクセス時 ‣ Map アクセス時の key の型違い(string/atom) ‣ Struct アクセス時の typo(コンパイルフェーズで気づけない) ‣ nil に dot access、など ほとんどはユニットテストで検出可能 しかし、テスト⽤のモック実装と現実の実装の間で返り値に差があったりすると… ‣ それでも staging 環境で気付ける ‣ 常⽤開発環境がない外部システムなら接続試験で…
  28. Elixir でよくある動的型付け⾔語っぽいミス Elixir での Web 開発について Map アクセス時の key の型違い(string/atom)

    iex> map = %{hoge: 100} iex> map.hoge 100 iex> map = map |> Jason.encode! |> Jason.decode!
 iex> map.hoge ** (KeyError) key :hoge not found in: %{"hoge" => 100} JSON を介したりするとついやってしまいがち atom は GC されないので、string → atom は雑にできない
  29. Elixir でよくある動的型付け⾔語っぽいミス Elixir での Web 開発について Erlang の Dialyzer という静的解析ツールがあるが、


    現状は個⼈のローカル環境でのサポート程度にしか利⽤できていない
  30. bitstring の操作⽀援が貧弱 Elixir での Web 開発について binary 向けオペレータは基本つかえない… が頑張ればなんとかなる #

    ݁߹ͷྫ iex> <<1, 2>> <> <<3>> <<1, 2, 3>> iex> <<1::1, 2::1>> <> <<3::1>> ** (ArgumentError) argument error (stdlib) eval_bits.erl:101: :eval_bits.eval_exp_field1/6 (stdlib) eval_bits.erl:92: :eval_bits.eval_field/3 (stdlib) eval_bits.erl:68: :eval_bits.expr_grp/4 (stdlib) erl_eval.erl:481: :erl_eval.expr/5 (iex) lib/iex/evaluator.ex:257: IEx.Evaluator.handle_eval/5 (iex) lib/iex/evaluator.ex:237: IEx.Evaluator.do_eval/3 # ΦϖϨʔλΛ͔ͭΘͣʹ݁߹ iex> << <<1::1, 2::1>>, <<3::1>> >> <<5::size(3)>>
  31. 放置気味なライブラリもやっぱりある Elixir での Web 開発について ⼈気ライブラリでもそういうものもある tzdata というタイムゾーン管理のライブラリ(累計ダウンロード数でhex.pmの1ペー ジ⽬にある定番ライブラリ)にリソースの開放漏れに関する PR

    を送ったときは8ヶ⽉ 後にマージされた ただこれはどの⾔語でもある問題な気がする
  32. 決済システム開発で便利だったこと Elixir での Web 開発について Erlang のエコシステムに乗っかれるのはやはり便利 6gram における ISO8583(クレジットカード取引のプロトコル)処理は

    Erlang ⽤ラ イブラリをベースに実装している ‣ Bitmap の処理や中間表現のみを利⽤し、フィールドの定義や変換処理は⾃前実装 ‣ こういう拡張性のある実装のライブラリは Elixir には存在しなかった
  33. 決済システム開発で便利だったこと Elixir での Web 開発について バイナリプロトコルの処理も不⾃由なくかける!(慣れれば) C⾔語などのスタイルでの処理に慣れている⼈にはまどろっこしく感じるところもあ りそう パターンマッチ、SpecialForms (<<1,

    2>> みたいなやつ) を使いこなすのが鍵
  34. 決済システム開発で便利だったこと Elixir での Web 開発について ログやスタックトレースの表⽰をコントロールできる PCI DSS 的にカード番号や CVC

    などがログにでるのはインシデント ‣ 標準の Logger が拡張性あるので JSON ログするついでにフィルター関数も呼ばれ るように拡張 ‣ v1.8 で導⼊された Custom Inspect Optionを利⽤するとより事故を回避しやすく ‣ CVC は3桁程度のため、カード番号のように正規表現で⼀括フィルタしづらく、
 どうやってエラー時などにもログに出さないようにするか悩ましかった ‣ Inspect Option 付の Struct に⼊れて引き回すことで不意の内容展開時も安⼼
  35. まとめ

  36. まとめ 6gram という新しいサービスがでました Elixir でのアプリケーション開発はいいところが⾊々ある 6gram、これからがんばっていきます!

  37. None
  38. なんで Elixir? Appendix すでに弊社の中では採⽤実績も複数ある選択肢だった 弊社で最初に Elixir を採⽤したのはリアルタイム通信を必要とするゲームのバックエ ンド 発⾜時点のメンバーが全員 Elixir

    経験者 個⼈的にも、⼊社以来サーバーサイドはほとんど Elixir を扱っていた ‣ 未経験者でもそれほど初期の学習コストが⾼くないことも知っていた 前プロジェクトの資産を活かせる 前プロジェクトも Elixir で、その資産も活かせるため⾃然な流れで採⽤