StripeでShared Customerを使ってSubscriptionプラットフォームを作る


## Stripe ConnectとStripe Billing
Stripeには、マーケットプレイス、シェアリングエコノミー、プラットフォーム型のビジネスに向けの決済プラットフォームであるStripe Connectというサービスがあります。。例えば、オークションサービスのように出品者と落札者をつなぐサービスで、落札者からの入金を直接出品者に送金することが可能になります。プラットフォームでは、そこからStripeの決済手数料と、プラットフォームの利用手数料を徴収することができます。([Stripe Connectの解説はこの記事などを参照](https://qiita.com/y_toku/items/7bfa42793801dfc5415d))

また、Subscription(継続課金)を行う為のStripe Billingという機能も用意されています。Stripe Billingは継続課金するサービス(Product)とそのプラン(Plan)を作成して、ユーザに定期的に課金することができます。([Stripe Billingの解説はこちら](https://qiita.com/y_toku/items/235b5e7ee00792edcbbf))

Stripe ConnectとStripe Billingを組み合わせ使うと、Subscriptionを提供するプラットフォームを作り、Stripe Connectを使ってユーザからの課金を、直接お店に送信しつつ、手数料を徴収する仕組みを実装することができます。

## 前提となるデータ
Stripe ConnectとStripe Billingに出てくるデータのモデルとそのIdは、次のようになります。Stripe Connectの決済フローは、Destination chargeとして、Custom Accountを使う前提で進めます。

- 課金されるユーザ/お客さん (Customer, CustomerId)
- 課金するお店/ベンダー (Custom Account, AccountId)
- 課金する製品/サービス (Product, ProductId)
- 課金プラン(Plan, PlanId)
- ユーザと課金プランを紐付けた継続課金(Subscription, SubscriptionId)

最終的に、PlanとCustomerを結びつけたSubscriptionを作成することをゴールとします。

## Shared Customer
今回作るSubscriptionプラットフォームサービスは、UberやAirBnBのようなイメージで、利用するユーザ（課金されるユーザ/お客さん）とサービスを提供するユーザ（課金するお店/ベンダー ）を直接結びつけ、都度課金ではなく継続課金(Subscription)を行うサービスです。例えば、毎月会費がある複数のクラブやグループを運営するようなサービスをイメージしてください。

Stripe BillingのSubscription機能を使って継続課金をし、Stripe Connectを使って入金されたお金からプラットフォームの手数料を引いて、クラブ/グループ/お店に直接送金します。

このケースでは、Product, Plan, Subscription, Customerの全てに同じAccoountIdを指定する必要があります。また、SubscriptionにはCustomerIdも指定する必要があります。

ここで、CustomerにAccoountIdを指定する必要があるということは、「課金されるユーザ/お客さん」が、「課金するお店/ベンダー」に紐づくということです。Customerと、AccountIdが紐づくと、「課金されるユーザ/お客さん」が、複数の「課金するお店/ベンダー 」が提供するサービスのSubscriptionを利用できないことになります。

ここで、Customerを複数のAccoountIdに紐付けるための**「Shared Customer」**の登場です。Shared Customerは、作成した「Customer」モデルの決済情報などのデータをそのまま引き継いて別の「Customer」モデルを作成することができます。「Customer」モデルのエイリアスです。
Shared Customerを作成するときに、AccoountIdを指定し、作成したShared CustomerをPlanに紐づけてSubscriptionを作成することで、Customerと、複数のCustom Accountが提供するPlanで継続課金をすることが可能となります。

[Shared Customerの詳細はここ](https://stripe.com/docs/connect/shared-customers)

## 実装

サンプルはNodeのコードです。

### ProductとPlan

Subscriptionに必要なProductとPlanを作成します。これらは、Custom AccountのaccountId に紐付けます。

```js:productの作成
export const createProduct = async (name, description, accountId) => {
  const product = await stripe.products.create({
    name: name,
    type: 'service',
    statement_descriptor: description
  }, {
    stripe_account: accountId
  });
  return product;
}
```

```js:planの作成

export const createPlan = async(amount, name, productId, accoundId) => {
  const plan = await stripe.plans.create({
    amount: amount,
    interval: "month",
    product: productId,
    nickname: name,
    currency: "jpy",
  }, {
    stripe_account: accoundId
  });
  return plan;
};
```


### Shared Customerの作成

Shared Customerを作成するには、customerId, accountIdを使ってcustomer tokenを作成します。そのcustomer tokenのidをcustomer作成時にsourceとして渡します。

```js:CustomerTokenの作成
const createCustomerToken = async (customerId, accountId) => {
  const token = await stripe.tokens.create({
    customer: customerId,
  }, {
    stripe_account: accountId,
  });
  return token;
}
```

```js:SharedCustomerの作成
export const createSharedCustomer = async(customerTokenId, accountId) => {
  const customer = await stripe.customers.create({
    description: "Shared customer",
    source: customerTokenId,
  }, {
    stripe_account: accountId,
  });
  return customer;
}
```
上記２つの関数を使って実際にShared Customerを作成します。

```js:sharedCustomerの作成
  const customerToken = await createCustomerToken(customerId, accountId);
  const sharedCustomer = await createSharedCustomer(customerToken.id, accountId);
```

これで、subscriptionを作成する用意ができました。プラットフォームが徴収する手数料が決済額の10%だとすると、application_fee_percentに10を指定します。Shared CustomerのcustomerIdを使って以下の関数を呼びます。

```js:SharedCustomerの作成
export const createSubscription = async (customerId, plan, accoundId) => {
  const subscription = stripe.subscriptions.create({
    customer: customerId,
    items: [{ plan: plan }],                                                                          
    application_fee_percent: 10,
  }, {
    stripe_account: accoundId
  })
  return subscription;
}
```

これで、毎月決まった金額を課金して、課金された金額からStripeの手数料とプラットフォームへの手数料を引いた金額がCustom Accountのユーザに送金されるようになります。


### 謝辞

SubscriptionとBillingが同時に使えないことに気がついて、StripeのUSのサポートチームに質問したところ、Shared Customerについて詳しく教えていただきました。ありがとうございます！！Stripeは丁寧にサポートしてくれるので、何かあれば問い合わせするのがおすすめです。