本記事は、決済サービスであるStripeについて紹介します。
はじめに
Stripeとはオンライン上での決済代行サービスを提供するSaaS企業です。このStripeを業務で触る機会に恵まれたのですが、APIサービスとしての完成度が本当に高いと感じました。
本記事では、そんなStripeの機能と設計の魅力について、特にエンジニア目線で感じた点を紹介していきます。
1. リソース = オブジェクト
Stripeの世界では、顧客、決済、価格などの全てのリソースはオブジェクトとして表現され、ユーザーのアクション等によってリアルタイムに変化していきます。各リソースの持つ情報が一箇所に集約しているため、APIの理解が簡単に出来るようになっています。
代表的なオブジェクト一覧
オブジェクト名 | 役割 |
---|---|
Customer | ユーザーを表すオブジェクト。サブスクや支払い情報が紐づけられる。 |
PaymentIntent | 支払いの実行と支払い状態の変化の追跡を行うオブジェクト。 |
PaymentMethod | 支払い方法を表すオブジェクト。クレカ情報などを持つ。 |
Subscription | Customerに紐付けることで継続的な支払いを行うオブジェクト |
Product | 商品やサービスを表すオブジェクト。 |
Price | Productの価格を表すオブジェクト。 |
2. Restfulな設計
Stripe APIはRESTful設計を採用しており、エンドポイントはリソースを表すURLとHTTPメソッドの組み合わせで構成されています。これにより、リソースの作成、読み取り、更新、削除といったCRUD操作を簡単に実行できます。また、CRUD以外のアクション(検索など)を行うエンドポイントに使用される単語もシンプルになっており、各エンドポイントの役割を簡単に把握することが出来ます。
顧客 エンドポイント |
---|
3. オブジェクト指向のSDK
Stripeが提供するSDKはオブジェクト指向に従って設計されています。各リソースはクラスとして定義され、インスタンス化されたオブジェクトを通じてアクションを行います。また、API操作はメソッドとして提供され、オブジェクト指向ならではの実装の抽象化が徹底されています。
# サブスク商品購入の例
subscription = Stripe::Subscription.create(subscription_params)
Stripe::Invoice.pay(subscription.latest_invoice)
ちなみにSDKは多言語対応しています。Firebaseより豊富かもしれません。各言語ごとにガイドも用意されており、利用環境を選ばないのも強みかなと思います。
4. バージョン管理
Stripe APIでは、URLの先頭にバージョン情報を埋め込んでいます。
例:/v1/customers/:id
バージョンの表現はサービスによって違いがあります。マイナーバージョンも含めてたり、vの文字が存在しなかったり、日付で埋め込んでいるものもあります。
大切なのは利用側にとって、現在のバージョンが簡単に分かることと、バージョン対応がしやすいことです。その点では、v1
という表記は一目でバージョンを示していると分かりますし、メジャーバージョンの更新タイミングのみで対応すればいいため、良い設計と言えます。
また、ドキュメントとしてバージョンの更新履歴やアップグレードガイドも用意されており、非常に親切な作りになっています。
5. Webhook
Stripe APIには、非同期でリアルタイム性を持つWebhookシステムがあり、Stripe内で発生した特定のイベント(支払い完了など)をアプリ側に通知するために使用されます。アプリ側は受け取ったイベントの種類に応じて、データの更新・ユーザーへの通知など必要に応じた処理を行う事が出来ます。
今回の自分が導入するにあたっては、不審請求時のSlackへの通知、サブスク更新時のアプリ側のデータ更新などの用途で使いました。
6. サブスクリプション管理
Stripe APIは、定期購読の自動更新機能を持っています。価格請求・サブスク状態の更新はStripe側で行い、前述したWebhook機能を使用して、アプリ側では変更通知のみを受け取り状態を同期させます。
商品にはお試し期間・税率・通貨などユースケースに合わせた細かい設定が可能です。ちなみに先日、サブスク商品の価格改定を行ったのですが、Apple Googleに比べて設定が非常に簡単でした。
7. テスト
Stripe APIには豊富なテスト機能が備わっています。まず、Stripeにはテスト環境があり、これは本番とほとんど同じ動作環境を提供してくれます。ですので、リリース時に環境の違いによる不具合を気にする必要はほぼありません。
決済系は様々なユースケースに対応するため、100以上のテストカードが用意されています。カード発行会社・発行国・エラー・不審請求・不正防止・返金など...これには自分も驚かされました。
タイムトラベル機能も先日リリースされました。これにより、アプリ側でサブスク更新時の処理が適切に行われるか、簡単に確認することが出来ます。
8. 不正使用の検知
Stripeには「Radar」という、不正使用を検知するための独自AIシステムが採用されています。アプリ側はRadarが算出したリスクスコアに応じて、購入禁止の措置を取ることが可能です。一度利用禁止したユーザーやカードが、別アカウントで再度決済を行おうとした場合、Stripe側で自動で拒否してくれるようになります。尚、有料プランでは、より細かい設定が出来るようになります。
9. セキュリティ
決済データはアプリ側ではなく、Stripe側が保存しています。ですので、アプリ側はカード番号が漏洩するといったリスクを気にすることなく利用が可能です。当のStripeはオンライン決済業界の最も厳格なセキュリティ基準に合格しているので、十分に安全と言えると思います。
10. CLI
Stripe APIはCLIを提供しています。CLIを通じて、リソースオブジェクトの操作や、Webhookの発火・監視ができ、開発・デバックを効率化することが出来ます。
# ローカルにイベントを転送
$: stripe listen --load-from-webhooks-api --forward-to localhost:3000
# 特定のイベントのテスト
$: stripe trigger ${イベント名}
# リソースの更新や取得
$: stripe ${リソース名} retrieve ${リソースID}
$: stripe ${リソース名} update ${リソースID} --カラム名=値
11. カスタマイズ性
Stripeの各リソースが提供するデータをもとに、決済機能だけでなくアプリ側で独自の利用方法を作ることも可能です。自分のチームでは、過去の決済情報をもとに業者の傾向を割り出し、業者の早期検知を行うシステムを開発しました。
12. 決済の多様性
以下全ての決済方法にStripeは対応しています。
- クレジットカード・デビットカード: Master, Visaなど、JCBも行けます。
- デジタル決済: Apple Pay, Google Payなど
- 銀行振り込み
- プリペイドカード
開発者目線では、これらの決済方法を一元化されたAPIを通じて処理可能なため、共通コードで様々な決済ケースに対応出来るのが良い点です。
13. ローコーディングでも導入可能
Stripeはサーバー側のコーディング無しで導入可能な「Stripe Elements」と、最小限のコーディングで導入可能な「Stripe Checkout」の2つのプランを提供しています。通常のStripe APIに比べれば、カスタマイズ性こそ劣るものの、エンジニアがいないチームや、短い開発期間で導入したいチームにとって、これらのオプションは魅力的なものだと思います。(実際、チームのディレクターの方が趣味サイトでStripe Elemtnsを使用してました笑)
14. ドキュメントが読みやすい
最後に、StripeドキュメントのUI・UXが素晴らしかったことが印象的だったのでいくつか紹介させて下さい。
-
リクエストとレスポンスの実例を提示することで、開発者がAPIの使用方法を具体的に理解出来るようになっています。加えて、各Attributesは型ごとに色付けがされています。芸が細かい...
-
各リソースのAttributesの情報も、見やすくするために以下の工夫がされています。
- 必須パラメータかどうかを見出しに表示している
- 型情報を見出しに表示している
- 各パラメーターへのリンク
- 別リソースに関する部分はリンク化している
-
レスポンシブ対応しており、モバイル端末からでもアクセスしやすくなっています。
Response Data | Request Param | Attributes | Responsive |
---|---|---|---|
おわりに
長くなりましたが、本記事は以上です。
Stripeの魅力が少しは伝わりましたでしょうか?...でもほんとに書くの疲れた笑