こんにちは、サイオステクノロジーの佐藤 陽です。
今回は、Stripe の API を使って Stripe Object の全件取得を行う方法についてご紹介します。
はじめに
決済プラットフォームを提供する Stripe は、API を通じて様々な情報を取得することができます。
今回は、Customer や Invoice などの Object を全件取得する方法についてご紹介します。
忙しい人向けに結論を先に言ってしまうと、Auto-Pagination の機能を使ってください!!!
…ということで、
Auto-Paginationを使ったときのStripe側の挙動なども確認したので
時間ある方は最後まで読んでいただければ幸いです。
今回は以下の.NET 系の環境で検証を行いました。
- C#
- ASP.NEC Core 6.0
ただ、言語やフレームワークに依存しない部分かと思うので
適宜読み替えて実装していただければと思います。
(Stripeのドキュメントにも各言語のサンプルコードがあります。)
ListAPI について
Stripe の API には List 系の API が多数用意されています。
例えば Customer を取得する ListAllCustomers や、Invoice を取得する ListAllInvoices などですね。
そして、この List 系の API なんですが、取得件数を指定するLimit というオプションが用意されており
A limit on the number of objects to be returned. Limit can range between 1 and 100, and the default is 10.
といった記載があります。
注目すべきは between 1 and 100ですね。
ListAllと言っておきながら、100 件までしか取得できない!!
と思ってました。
もちろん、starting_after のオプションを使って順次問合わせすればできるかもしれないですが、面倒だなー。
と思ってました。
が、当然ながら、そんなことはありませんでした。
ちゃんと全件取得する方法が用意されていました。
今回は、その方法をご紹介していきます。
全件取得
どう実装するかというと、Stripe の Auto-Pagination という機能を使います。
ちゃんと公式ドキュメントにも載ってましたね…、見落としてました。
今回、例えば Invoice を全件取得するには以下のように実装するようです。
public IEnumerable<Invoice> GetAllInvoices(){
var service = new InvoiceService();
var options = new InvoiceListOptions {
Limit = 10
};
List<Invoice> invoices = new();
foreach (InvoiceListOptions option in options)
{
InvoiceService service = new();
await foreach (var invoice in service.ListAutoPagingAsync(option)) {
stripeInvoices.Add(invoice);
}
}
return invoices
}
これで 100 件を超える Invoice であっても、全件取得することができました。
ただ、全件取得するのであれば Option として設定するLimitとしてはどのような意味があるのでしょうか?
この Auto-Pagination がどのような振る舞いをしているか、少し探ってみたいと思います。
実行内容
今回、手元の環境で Invoice が 9 件登録されている Customer が居たので、
その Customer に対して以下のようなコードを実行してみました。
public IEnumerable<Invoice> GetAllInvoices(){
var service = new InvoiceService();
var options = new InvoiceListOptions {
Customer = {CustomerId} //対象Customerに限定
Limit = 1 //上限を1件とする
};
List<Invoice> invoices = new();
foreach (InvoiceListOptions option in options)
{
InvoiceService service = new();
await foreach (var invoice in service.ListAutoPagingAsync(option)) {
stripeInvoices.Add(invoice);
}
}
return invoices
}
実行すると、invoices の Count の値が[9]となっており、全件取得できていることが確認できました。
ここで Stripe のダッシュボードから API の実行履歴を見てみます。
「開発者」の項目から「ログ」のタブを開きます。
すると、先ほどプログラムを実行した時間の前後で、9 回 API が実行されていることが分かります。
API のオプションとしては指定した通り、limit=1が指定されてますね。
あくまで 1 回の実行あたりの Object 取得数はlimitで指定した値となり、
Stripe 側で、全て取得できるまで API を繰り返し実行しているようです。
そのため、limit を小さくすると無駄に実行回数が増えてしまうので注意です。
とりあえず limit は 100 に設定しておくのがよさそうです。
余談ですが、starting_afterのオプションが追加されている事が分かるので、Stripe側では
- 指定されたLimitでListAPIを1度実行
- APIのレスポンスからリストの最後のオブジェクトIDを参照
- 2.で取得されたオブジェクトIDをstarting_afterオプションとして追加し、再度ListAPIを実行
という流れで、3.と2.を繰り返し、
ListAPIのレスポンスのhas_moreパラメータがfalseとなったら終了する、といったロジックが組まれているように見えます。
まとめ
今回は Stripe の Object を全件取得する方法についてご紹介しました。
単純に ListAll を使うだけでは最大 100 件しか取得できませんが、Auto-Pagination 機能を使う事で一括取得が実現できました。
ただし、あくまで Stripe 側としては複数回 API が実行されているため、コール回数など注意しましょう。