Stripeコードスニペット: customer idからデフォルトの支払い方法のデータを取得する

そのStripe Customerのデフォルト支払い方法のデータを引っ張ってくるコードです。


export const test = async (customerId: string) => {
  const customer = (await stripe.customers.retrieve(customerId)) as Stripe.Response<Stripe.Customer>
  if (customer.deleted) {
    throw new Error('No such customer')
  }
  const defaultSourceId = customer.default_source
  if (!defaultSourceId) {
    throw new Error('Any payment method does not registered')
  }
  const source = await stripe.sources.retrieve(typeof defaultSourceId === 'string' ? defaultSourceId: defaultSourceId.id)
  return source
}

簡単な説明

customers.retrieveをTypeScriptで使うときは、DeletedCustomer型に注意する

TypeScriptでcustomers.retreiveを実行すると、あるはずの型がIDEやビルドで存在しない扱いになることがあります。これはcustomers.retreiveのレスポンス型がDeletedCustomer | CustomerのUnionになっているためです。

DeletedCustomerはcustomer.deletedtrueですので、除外してasでキャストしてやるとよいでしょう。

もしくはTypeGuard関数を用意してやると良いです。


const isActiveCustomer = (customer: Stripe.Customer | Stripe.DeletedCustomer): customer is Stripe.Customer => {
  return customer.deleted !== true
}
... 
  const customer = await stripe.customers.retrieve(customerId)
  if (!isActiveCustomer(customer)) {
    throw new Error('No such customer')
  }
  const defaultSourceId = customer.default_source

customer.default_sourceはStringとSource型のUnion

基本的にcustomers.retreiveで返ってくるものはStringでIDだけ入っていることがほとんどです(体感値)。ただ、型定義上ではSource Objectになる可能性もあるとされています。

なので、sources.retrieveの引数を渡す時には、typeofで判定してやると良いでしょう。

  const source = await stripe.sources.retrieve(typeof defaultSourceId === 'string' ? defaultSourceId: defaultSourceId.id)

ちなみにcustomer.default_sourceはNullableなので、事前にif (!customer.default_source)で処理してやる必要があることにも注意です。

Comment