#Stripe Connect とは
Stripe Connect とはマーケットプレイス、シェアリングエコノミー、プラットフォーム型のビジネスに向けた最適な決済を提供する製品です。例えば、ライドシェアのように、ドライバーと乗客をつなぐビジネスでは、乗客の決済から、ドライバーとプラットフォームへの振込まで完全に自動化することができます。また、予約システムや E コマースツールのように、利用者に対して決済機能を提供したいケースにも、Stripe Connect は最適です。他にもクラウドファンディング、トラベルサイト、請求書発行サービス、などなど様々なケースで利用されています。
- Customer(顧客): 購入者でありお金を支払う方。上の図で緑。
- Platform(プラットフォーム): その名の通りプラットフォームを提供する方。上の図の青。
- Connected accounts: プラットフォームを利用してサービスを提供し、入金を受ける方(子アカウントとも呼ばれます)。上の図のピンク。
Connect を理解して 、実装するにはアカウントタイプと決済フローを特定する決済作成方法を理解することがまずはとても重要です。
- アカウントタイプ: プラットフォームと子アカウントをどのように連結・管理するか
- 決済作成方法: 資金フローをどのようにするか
#Connect のアカウントタイプ
プラットフォームとプラットフォームユーザである売り手(資金の受け手、子アカウント)を連携するには、日本では二つのタイプがあります。Standard アカウントと Custom アカウントです。このアカウントタイプの違いにより可能なこと、向いていることが異なりますので、概要を説明したいと思います。(Express アカウント は 米国のみ利用可能ですのでここでは省略します)
##アカウントタイプを決める上で考えておきたいポイント
まず、アカウントタイプを決める前に、下記のようなことを考えておくと比較的スムーズです。
- 決済フローの詳細
- 資金(決済から子アカウントへの入金まで)フローをどこまでコントロールしたいか
- 売り手(資金の受け手)の登録フローや料金体系、売上管理画面(ダッシュボード)を自社で提供したいか
- アカウントの責任の所在はプラットフォームにしたいか、子アカウントにしたいか
などです
それでは、ここからは売り手のアカウント(子アカウント)をどのように連携・作成していくかをアカウントタイプごとに解説します。
##Standard アカウントとは
一般の Stripe ユーザのように、売り手自身が Stripe アカウントを Stripe のフォームから作成し、アカウントを管理します。Stripe の管理画面(ダッシュボード)へ、売り手自身がアクセスできるようになります。こちらは、Shopify や Jimdo などの E コマースプラットフォームや、オンライン予約システムを提供するプラットフォーム、オンラインで請求書等を管理できるプラットフォームのようなケースで多く利用されています。売り手自身が独自にウェブサイトなどを持ち、プラットフォームから決済機能を連携させるなどのユースケースです。アカウントの管理は売り手自身が行うので、チャージバックや返金、マイナスの残高が発生した場合は売り手自身が責任を持ちます。
##Custom アカウントとは
プラットフォームがユーザエクスペリエンスをフルカスタマイズしたい場合に向いています。子アカウントの Stripe アカウント登録から管理まで、全てをプラットフォームが提供し管理するため、Stripe ブランドを売り手に見せることなく決済周りの設定を構築できます。また Custom では、決済から振込までの資金フローも柔軟にコントロールできるので、あらゆるケースに対応できます。例えば、予約時からサービス提供までの時間が比較的長い場合、プラットフォームが子アカウントへの入金タイミングをコントロールしたいというケースがよくありますが、そのようなときには Custom がおすすめです。また、モール型のビジネスのように、モール上で複数店舗から商品を買う場合には、一つの決済を複数の店舗に分けたいという場合もありますが、この場合は Custom のみ対応が可能です。
#アカウントを作成する
それでは、実際に子アカウントを作成していきたいと思います。
##Standard アカウントを作成する
Standard アカウントをプラットフォームと連結するために OAuth を利用して実装します: https://stripe.com/docs/connect/standard-accounts
(1). OAuth のリンクを作成するための2つの要素
-
client_id
: ダッシュボードのプラットフォーム設定ページに、client_id
(ca_xxxx) が保存されています。 -
redirect_uri
: こちらは、ダッシュボードのプラットフォーム設定ページに Redirect 先の URI を事前に設定しておきます。
Connect ボタンを設置して、連携を促すと良いと思います。Connect ボタンのリソースは こちら にあります:
https://connect.stripe.com/oauth/authorize?response_type=code&client_id=ca_32D88BD1qLklliziD7gYQvctJIhWBSQ7&scope=read_write"
(2). プラットフォームを利用するユーザが子アカウントを作成(もしくは連結)します。
Stripe のアカウント作成プロセスと同じフォームが立ち上がり、アクティベーションまで一気に完了させます。
すでにアカウントを持っている場合は、連携するかどうかを選ぶだけです。
新規にアカウントを作成する場合には、フォームが立ち上がります。
Standard アカウントで連携する場合には、このプロセスが必須になりますが、このようなフォームではなく自分たちのプラットフォームのデザインで一貫させたい場合、Custom アカウントを利用することで実現できます。
(3). それを受けて、プラットフォームがアカウントを作成を完了します。
成功すると下記の情報が Stripe より送信されます:
scope
-
state
(もしあれば) authorization_code
https://stripe.com/connect/default/oauth/test?scope=read_write&code={AUTHORIZATION_CODE}
(4). 受け手のアカウント情報を受け取る
ここまでに得た情報を元に、POST リクエストを送ると、子アカウントの認証情報を受け取ることができます。
curl https://connect.stripe.com/oauth/token \
-d client_secret=sk_test_BQokikJOvBiI2HlWgH4olfQ2 \
-d code="{AUTHORIZATION_CODE}" \
-d grant_type=authorization_code
そして、レスポンスを受け取ります。
{
"token_type": "bearer",
"stripe_publishable_key": "{PUBLISHABLE_KEY}",
"scope": "read_write",
"livemode": false,
"stripe_user_id": "{ACCOUNT_ID}",
"refresh_token": "{REFRESH_TOKEN}",
"access_token": "{ACCESS_TOKEN}"
}
ここで得る情報、特に stripe_user_id
は、子アカウントの情報を利用する際に必要となりますので保存しておきましょう。
さらなる詳細は、ドキュメントをご覧ください: https://stripe.com/docs/connect/standard-accounts
##Custom アカウントを作成する
Custom アカウントを作成する前に、下記のことをよく頭に入れておく必要があります。
- API のバージョンは、 2014-12-17 より新しいバージョンを利用します。
- 利用規約に、Stripe が決済周りのことを行う旨を追加する必要があります。サンプルの文言がありますので、こちら をご覧ください。より詳しくは、ご自身の法律アドバイザーにご確認ください。
- 重要情報へのアクセスを依頼する: 本人確認書類(運転免許証)や住所などを、Stripe へプラットフォームからお送りいただくことになりますので、その点も合意していいただくとよいと思います。
- 子アカウントがサポート対応国にいること: https://stripe.com/global
- 確率としては低いのですが、Custom アカウントを利用の場合、子アカウントに損失があったり、不正利用等があったりすると、Stripe 上の責任はプラットフォームが負います。このような場合には子アカウントへ請求するなど別途対応策を考えておくとよいかと思います。
これらを踏まえて、Custom アカウントを作成します。
(1). Custom アカウントを作成
Custom アカウントを作成するためのフォームはプラットフォームが提供します。下記に示す必須情報を集められるように、フォームを作成してください。
最初に必要なパラメータは、country
(国)です。それさえあれば、アカウント自体は作成できます。国は後日変えられませんのでご注意を。
acct = stripe.Account.create(
country="JP",
type="custom"
)
そして、レスポンスを受けます。
{
...
"id": "acct_xxxx",
"keys": {
"secret": "sk_live_xxxx",
"publishable": "pk_live_xxx"
},
"type": "custom"
...
}
この id
が、今後、子アカウントの情報を扱ったり、リクエストを送ったりする際に、とても重要になりますので、忘れずに保存します。
(2). アカウントの必須情報
そして、アカウントが作成できたら、各国ごとに定められた子アカウントが本番環境で利用できるようにするための必須情報を更新していきます。(1) に下記の情報をまとめてしまうことももちろん可能です。
この記事は日本語ですので、日本として下記の例を説明します。
account = stripe.Account.retrieve({CONNECTED_STRIPE_ACCOUNT_ID}) #ここに(1)で保存した`id`を利用し対象のアカウントを特定
account.legal_entity.type="individual"
account.legal_entity.last_name_kana="トク"
account.legal_entity.last_name_kanji="徳"
...
account.save()
この要領で必要な情報を得て、リクエストを送ります。下記必須項目の解説です。
{
"individual": {
"external_account": "銀行口座",
"legal_entity": {
"address_kana":{
"postal_code": "郵便番号(カナ)",
"state": "都道府県(カナ)",
"city": "区市町村(カナ)",
"town": "町名(丁目まで、カナ)",
"line1": "番地、号(カナ)",
"line2": "建物・部屋番号・その他 (任意、カナ)"
},
"address_kanji":{
"postal_code": "郵便番号(漢字)",
"state": "都道府県(漢字)",
"city": "区市町村(漢字)",
"town": "町名(丁目まで、漢字)",
"line1": "番地、号(漢字)",
"line2": "建物・部屋番号・その他 (任意、漢字)"
},
"dob": {
"day": "生年月日(日)",
"month": "生年月日(月)",
"year": "生年月日(年)"
},
"phone_number": "電話番号",
"type": "individual(個人)"
},
"tos_acceptance": {
"date": "アカウント契約同意 timestamp",
"ip": "アカウント契約同意時の IP アドレス"
},
"first_name_kana": "名前(カナ)",
"first_name_kanji": "名前(漢字)",
"last_name_kana": "姓(カナ)",
"last_name_kanji": "姓(漢字)",
"gender":"性別"
},
"company": {
"legal_entity": {
"business_name": "会社名",
"business_name_kana": "会社名(カナ)",
"business_name_kanji": "会社名(漢字)",
"business_tax_id": "会社法人等番号"
},
"address_kana":{
"postal_code": "郵便番号(会社、カナ)",
"state": "都道府県(会社、カナ)",
"city": "区市町村(会社、カナ)",
"town": "町名(丁目まで、会社、カナ)",
"line1": "番地、号(会社、カナ)",
"line2": "建物・部屋番号・その他 (任意、会社、カナ)"
},
"address_kanji":{
"postal_code": "郵便番号(会社、漢字)",
"state": "都道府県(会社、漢字)",
"city": "区市町村(会社、漢字)",
"town": "町名(丁目まで)(会社、漢字)",
"line1": "番地、号(会社、漢字)",
"line2": "建物・部屋番号・その他 (任意、会社、漢字)"
},
"personal_address_kana":{
"postal_code": "郵便番号(担当者、カナ)",
"state": "都道府県(担当者、カナ)",
"city": "区市町村(担当者、カナ)",
"town": "町名(丁目まで、担当者、カナ)",
"line1": "番地、号(担当者、カナ)",
"line2": "建物・部屋番号・その他 (任意、担当者社、カナ)"
},
"personal_address_kanji":{
"postal_code": "郵便番号(担当者、漢字)",
"state": "都道府県(担当者、漢字)",
"city": "区市町村(担当者、漢字)",
"town": "町名(丁目まで、担当者、漢字)",
"line1": "番地、号(担当者、漢字)",
"line2": "建物・部屋番号・その他 (任意、担当者、漢字)"
},
"dob": {
"day": "生年月日(日)",
"month": "生年月日(月)",
"year": "生年月日(年)"
},
"phone_number": "担当者電話番号",
"type": "company(会社)",
"tos_acceptance": {
"date": "アカウント契約同意 timestamp",
"ip": "アカウント契約同意時の IP アドレス"
},
"first_name_kana": "担当者の名前(kana)",
"first_name_kanji": "担当者の名前(漢字)",
"last_name_kana": "担当者の姓(カナ)",
"last_name_kanji": "担当者の姓(漢字)",
"gender":"性別"
}
}
Individual が個人事業主、Company が法人として登録する際に必要になる情報です。
なお、external account の銀行口座情報は、別のセクションで記載しますが、銀行口座情報も (1) に含めて一つとしてしまうことも、もちろん可能です。
会社法人等番号は登記簿に記載されている 12 桁の番号で、13 桁の法人番号とは微妙に異なります。13 桁の法人番号を持っている場合は、先頭の 1 桁目を削除したものが会社法人等番号となります: https://www.nta.go.jp/mynumberinfo/FAQ/03houjinbangoukankei.htm
(3). 本人確認書類の提出
子アカウントへの振り込みがあるため、子アカウントの本人確認が必要となります。下記のドキュメントを参考にして、本人確認を提出します:
- ドキュメント: https://stripe.com/docs/connect/identity-verification
- API でドキュメントを送る: https://stripe.com/docs/connect/identity-verification-api
日本の場合、日本で発行された政府発行の書類が有効です: https://support.stripe.com/questions/jp-why-do-i-need-to-upload-a-scan-or-photo-of-my-passport-or-driver-s-license
###Custom アカウントの状況を確認する
ここで最もよくいただく質問の一つに、子アカウントに不足している情報を確認するにはどうすればよいか、とお問い合わせいただくことがあります。これは、Account オブジェクトにある、verifications
パラメータを見て確認します。ここで fields_needed
に表記があるものが不足情報です。
また、子アカウントで決済や入金が可能かどうかを知りたい、という問い合わせもいただきます。決済ができるか確認するには、Account オブジェクトの charges_enabled
、入金ができるかを確認するには、payouts_enabled
を確認します。
##アカウントタイプの比較表
これまで、Standard アカウントと Custom アカウントについて説明してきましたが、いったん特徴をまとめます。
機能 | Standard | Custom |
---|---|---|
Stripe アカウントの登録フロー | OAuth | API |
子アカウントへの振込みタイミングの制御 | 不可 | 可能 |
Stripeダッシュボードへのアクセス | あり | なし |
本人確認書類の提出 | Stripe ダッシュボード | プラットフォーム経由 |
ユーザサポート* の責任 | 子アカウント | プラットフォーム |
返金やチャージバックの責任 | 子アカウント | プラットフォーム |
開発工数 | 少 | 中 |
Connect 料金体系 | 追加料金なし | 別途料金あり |
- アカウントや決済周りの質問があると、Standard では子アカウントが自身が Stripe に問い合わせをし、Custom の場合はプラットフォームへまずは問い合わせをすることになります。プラットフォームでもよくわからない場合は、プラットフォームが代理で Stripe へ問い合わせをします。
##共通
Custom アカウントは基本的には API 経由で処理しますが、Standard アカウントでも API 経由で処理出来ることがあります。
Custom、Standard アカウント問わず、API 経由で処理可能なものは下記になります。
- 決済を行う
- 決済作成方法の特定
- 返金とチャージバック対応
言い換えると、Account 情報(銀行口座情報や個人・ビジネス情報など)以外は基本どちらのタイプでもアクセス出来ます。
このあたりの概要はドキュメントではこちらです: https://stripe.com/docs/connect
#資金フローを決める決済作成方法
3つあります。
- Direct charge (Standard アカウントにおすすめ)
- Destination charge (Custom アカウントにおすすめ)
- Separate charges and transfers (Custom アカウントのみ利用可能)
##Direct charge: 子アカウントに支払いを作成する
売り手 (子アカウント) に支払い(Charge)を作成し、その支払いの一部をプラットフォームに配分する方法です(配分しなくてももちろん大丈夫です)。子アカウントに支払いが付きますので、子アカウントが決済手数料を負担したり、返金対応したり、チャージバックに対応したりします。そのため、Standard アカウントがこちらに向いています。
###決済
例えば、10000円の支払いを子アカウントが行い、そのうち300円をプラットフォームに配分するためには、下記のようになります。
stripe.api_key = '{Platform Secret API Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="usd",
source="tok_visa",
application_fee=300,
stripe_account="acct_1BmuwtAXNafFOIBB",
)
上記の図では、少々サンプルの数字とは別物になりますが、流れを理解するのに役に立つかと思います。Chargeが顧客が支払う対象です。この10000円のお支払いの場合、いくら子アカウントが最終的に得て、プラットフォームはいくら得られるかというと(Stripeの決済手数料は 3.6% です):
- プラットフォーム: 300円が振込まれます。
application_fee
には、Stripe 手数料はかかりません。 - 子アカウント: 9340円が振込まれます = 10000 - 360(Stripe手数料) - 300(プラットフォーム手数料)
参考ドキュメント: https://stripe.com/docs/connect/direct-charges
###返金
返金時のフローもとても大切になります。ポリシーで事前に、お客様(購入者)への返金時にプラットフォーム手数料も返すかどうかなど決めておく必要があるでしょう。例えば、お客さまが返金を要求された場合には、プラットフォーム手数料を返すというポリシーの場合は、以下のようにリクエストします。
refund = stripe.Refund.create(
charge="{CHARGE_ID}", #ch_xxxx
refund_application_fee=True,
stripe_account="{CONNECTED_STRIPE_ACCOUNT_ID}", #acct_xxxx
)
返金時にrefund_application_fee
をtrue
にすると、プラットフォーム手数料も同時に返金することができます。このあたりは、返金ポリシーと連携させておく必要があると思います。
API リファレンス: https://stripe.com/docs/api#create_refund-refund_application_fee
##Destination charge: プラットフォームに支払いを作成し、配分先の子アカウントを指定する
こちらはプラットフォームに支払いを作成し、子アカウント(destination、資金の着地点)へいくら配分するかを決めるタイプです。プラットフォームに支払いが付き、フローをコントロールしますので、Custom アカウントに向いています。
まずはサンプルコードから。10000円の決済のうち9000円を子アカウントへ配分したいという場合を想定してみます。
charge = stripe.Charge.create(
amount=10000, #購入者が支払う金額
currency="jpy", #通貨
source="tok_visa",
destination={
"amount": 9000, #子アカウントへいくら配分するか
"account": "{CONNECTED_STRIPE_ACCOUNT_ID}", #子アカウントをここで指定します
}
)
この場合、誰がいくら得るかというと
- プラットフォーム: 640円= 10000 - 360(Stripe 手数料) - 9000(子アカウントが得る金額)
- 子アカウント: 9000円
つまり、決済手数料は Charge に対して付きますので、プラットフォームが負担します。子アカウントには、Stripe 決済手数料がいくらだったかなどがわからず、完全にプラットフォームがいくら子アカウントへ配分するかなどを決めることができます。もちろん、手数料などの表示を独自で開発し、ダッシュボードなどに表示させて子アカウントが確認できるようにすることも可能です。
参考ドキュメント: https://stripe.com/docs/connect/destination-charges
###用語の解説
Destination charge をすると、新たな用語が出てきます。Transfer、Payment という用語です。こちらを簡単に解説します。
- Transfer: 「プラットフォームから子アカウント」への残高の移動という意味になります。このドキュメントで「送金」という場合は
Transfer を意味します。日本語FAQ - Payout: 銀行口座への入金のこと。このドキュメントで入金、振込みと表現されているものです。
- Payment: これは子アカウントの売上という意味になります。
###返金時の対応
Direct charge と同じように、返金が発生した場合の対処を考えておくことをおすすめします。返金が起き、子アカウントへ Transfer した残高をプラットフォームへ戻す場合には、以下のようになります。
refund = stripe.Refund.create(
charge="{CHARGE_ID}",
reverse_transfer=True, #Transferした金額をプラットフォームへ戻す
)
reverse_transfer
をtrue
として渡しますが、デフォルトは false です。
ドキュメント: https://stripe.com/docs/api#create_refund-reverse_transfer
##Separate Charges and Transfers: 支払いと送金を分ける
これは、Charge と Transfer を分ける決済方法です。この方法は Custom アカウントのみ利用可能です。Charge をプラットフォームで作成した時、すぐに子アカウントへ Transfer を行わず、複数に分けたり、時間をある程度おいて、子アカウントへ配分する方法です。モール型のマーケットプレイスのように一つの決済で複数のオンライン店舗から購入するケースや、プラットフォームとしての利用料は毎月いくら払っていただき、提携しているサービスを利用し放題のようなサービスで、決済時には受け手が決まっていない場合などに使われます。
この方法ですと、Charge と Transfer が別になるため、マニュアルのアプローチが多くなります。
まず、Charge と Transfer を紐付ける必要があります。そこで鍵となるのが、**transfer_group
**です。
# Create a Charge:
charge = stripe.Charge.create(
amount=10000,
currency="jpy",
source="tok_visa",
transfer_group="{ORDER10}",
)
上記のように、transfer_group
を指定することで、この決済を後で特定できるように最初に履歴を残しておきます。
例えば、上記の決済を二つの子アカウントへ送金したいという場合には、下記のように指定します。
# 一つ目の子アカウントへ7000円送金:
transfer = stripe.Transfer.create(
amount=7000,
currency="jpy",
destination="{CONNECTED_STRIPE_ACCOUNT_ID}",
transfer_group="{ORDER10}",
)
# 二つめの子アカウントへ2000円送金:
transfer = stripe.Transfer.create(
amount=2000,
currency="jpy",
destination="{別の_CONNECTED_STRIPE_ACCOUNT_ID}",
transfer_group="{ORDER10}",
)
上記のように、tranfer_group
は同じですが、送金先を分けています。
この一連のやり取りではプラットフォームが Stripe fee を負担しますので、最終的には:
10000 - 360 - 7000 - 2000 = 640 円が残高として残ります。
###返金
お客さまへの返金は、プラットフォームから行いますのでとてもシンプルです。
refund = stripe.Refund.create(
charge="{CHARGE_ID}",
)
これでお客さまへの返金は完了しますが、子アカウントへ送金した残高を戻すかは別作業となります。
###子アカウントからプラットフォームへ送金を戻す
Reverse transfer API を用いることで、子アカウントへ送金した残高をプラットフォームへ戻すことができます。
transfer = stripe.Transfer.retrieve("{TRANSFER_ID}")
transfer.reversals.create()
上記のサンプルは全額ですが、一部を残高へ戻したい場合は、amount
を指定します。
###on_behalf_of
を使い、子アカウントの代わりに決済をする
Destination charge をした場合は子アカウントの国を見て、決済をする通貨や料金体系が決まりますが、この Charge と Transer を分けて作る際には、それがなされません。多国にまたがってサービスを提供する場合は、為替変換などが生じますのでとても大事になってきます。
そこで、on_behalf_of
を利用することで、destination charge と同じように、on_behalf_of
で指定された子アカウントの国の通貨や料金体系に合わせて決済が出来るようになります。
charge = stripe.Charge.create(
amount=1000,
currency="jpy",
source="tok_visa",
on_behalf_of="{CONNECTED_STRIPE_ACCOUNT_ID}"
)
###Source_transaction を使って決済と送金を紐付け、エラーを減らす
Charge と Transfer を分ける決済方法を使うと、場合により利用可能なプラットフォーム上の残高が足りないために、子アカウントへの送金ができないといったエラーが起こることがあります。
プラットフォームから子アカウントへの残高の送金するにはプラットフォームにて利用可能("available"と表現され、入金や送金が可能な状態が利用可能)な残高が必要です。日本の場合、該当の決済が利用可能となるまで4営業日かかります。
そうすると、決済直後に子アカウントを指定して送金すると、プラットフォームに利用可能な残高がないというエラーが多発します。このエラーを防ぐのがsource_transaction
です。
Transferと同時に、source_transaction
を紐付けます。
transfer = stripe.Transfer.create(
amount=1000,
currency="jpy",
source_transaction="{CHARGE_ID}", #ここです
destination={CONNECTED_STRIPE_ACCOUNT_ID}",
)
該当時に利用可能な残高がなくても、該当決済をsource_transaction
を指定することで、該当の決済が利用可能になった時、自動的に送金がされます。こちらの場合、決済時に指定した transfer_group
を指定しなくても自動で紐付いて来ます。
#アカウントタイプと決済作成のポイントまとめ
これまで、アカウントタイプと決済作成を説明してきました。少しまとめてみます。
- アカウントタイプ: プラットフォームとどのように連携するかを決めるもの(Standard と Custom)
- 決済作成方法: 資金フローを決めるもの (Direct Charge, Destination Charge, Separate Charges and Transfers)
決済作成方法 | よくあるユースケース | サンプルビジネス | おすすめのアカウントタイプ |
---|---|---|---|
Direct Charge | - 購入者と子アカウントが直接取り引きを行う - それぞれの子アカウントが独立した決済を行う |
- Eコマースビルダー - 自社ツールに決済機能を追加する など |
Standard |
Destination Charge | - 購入者がプラットフォーム上で子アカウントの商品やサービスに対して支払う - 一つの決済に関わる子アカウントは1つ |
- Lyftのようなシェアリングサービス - クラウドファンディング |
Custom |
Separate Charges and Transfers | - 一つの決済に複数の子アカウントが関わる - 決済時に子アカウントが不明 - 決済と送金のタイミングが異なる |
- モール型ビジネス - クリーニングプラットフォームのようなクリーニング予約時には小アカウントが不明なとき |
Custom のみ利用可能 |
Custom アカウントで、Direct chargeを行うと、最終的にはすべての責任を持つプラットフォームに決済の情報がなかったり、ダッシュボードにアクセスできない子アカウント側に決済の情報があったりと不便ですので、Direct charge は Standard に対して行い、Custom では Destination charge もしくは Separate charges and transfers を強くおすすめ します。
#入金(子アカウントへの振り込み)について
まず、Custom アカウントの場合は、子アカウントの銀行情報もAPI経由で更新します。ここももっともよくつまづくポイントで、入金がなかなかできないことが散見されます。
##子アカウントの銀行情報を登録
銀行口座の情報は、External accountです。たとえば、新規に口座情報を登録する場合は、下記のようになります。
account = stripe.Account.retrieve({CONNECTED_STRIPE_ACCOUNT_ID})
account.external_accounts.create(external_account= {
'object':'bank_account',
'account_number': '00012345',
'routing_number': '1100001', #銀行コード+支店コード
'account_holder_name':'トクテスト(カ',
'currency':'jpy',
'country':'jp',
})
ここでよくある質問がrouting_number
です。これは、銀行コードと支店コードを連結させたものをあてます。例えば、銀行コードが1100、支店コードが001の場合、routing_number
は 1100001 とします。
また、口座名義人がマッチしないというエラーがとても多く散見されます。会社の場合は、カブシキガイシャ、カ)、(カ など、正しいものを入力する必要がありますので、こちらは登録前に確認いただくことをおすすめします。
こちらのFAQがとても参考になります:
- http://www.smbc.co.jp/direct/help_furikomi/14.html
- http://www.smbc.co.jp/direct/help_furikomi/15.html
- https://faq01.bk.mufg.jp/faq/show/823
- https://www.mizuhobank.co.jp/direct/goriyo/furikomi/uketorininmei.html
##入金スケジュール
デフォルトですと、下記になります。
"payout_schedule": {
"delay_days": 4,
"interval": "weekly",
"weekly_anchor": "friday"
}
-
delay_days
: 決済が利用可能(入金や送金が可能)になるまでの営業日数。4 の場合は、決済完了日から 4 営業日後から入金・送金が可能 -
interval
: 入金サイクルのデフォルトは weekly (毎週自動)ですが、monthly (毎月自動)にすることもできます。 -
weekly_anchor
: 何曜日に振り込むか(月曜は時差等の関係で不具合があるので避けてください。)Monthly とした場合は、毎月振り込む日付monthly_anchor
を指定します。
これらを利用し、子アカウントへの入金サイクルを調整ができます。
より詳しくはこちらをご覧ください: https://stripe.com/docs/connect/payouts#payout-schedule
##入金タイミングをプラットフォームがコントロールする
Custom アカウントを利用する主な用途の一つに、子アカウントへの入金タイミングをコントロールしたいというケースがあります。クラウドファンディングや予約を伴うサービスの場合、決済時には子アカウント入金はせず、サービスがなされた時に入金したいというケースです。
このような場合には、manual payout (手動の入金)を利用します。Spacemarketさんが、Stripe のユーザコミュニティでご登壇されていた際のスライドがとても参考になりますので、まずご紹介させていただきます: http://blog.spacemarket.com/code/stripe-manual-payments/
入金タイミングをマニュアルにするには、payout_schedule[interval]
を manual
とします。Manual とすると、Payout 処理がされると入金に至る仕組みです。なお、決済が完了してから 90 日間以内に Payout をしてください。これは入金なので、子アカウントの残高から子アカウントの銀行口座へ入金するための処理となります。
例えば、子アカウントに1000円入金処理したいというサンプルは、下記のようになります。
stripe.Payout.create(
amount=1000,
currency="jpy",
stripe_account=CONNECTED_STRIPE_ACCOUNT_ID,
)
なお、manual payout の場合、入金処理をしてから 2 営業日ほど着金までに時間がかかります。
- 更に詳しくは、こちらのドキュメントをご覧ください: https://stripe.com/docs/connect/payouts#using-manual-payouts
- テストで利用できる子アカウント用のテスト銀行情報はこちらです: https://stripe.com/docs/connect/testing
#アカウント残高(Account Balance)の考え方
Connect を利用する際には、アカウントの残高(ドキュメント上では Balance)の考え方がとても重要です。Standard も Custom も、Stripe アカウントという点では同じです。すべての Stripe アカウントには残高があり、二つのステータスに分かれています。
-
pending
: まだ入金が可能ではない状態 -
available
: 入金が可能な状態(管理画面では利用可能と表示されます)
決済(Charge)が「利用可能」になるまでに日本のアカウントでは4営業日となります。Connect
を利用しない Stripe アカウントの場合、まず「決済金額 - Stripe 手数料」がpending
の残高に反映され、4営業日をすぎると、available
の残高となる仕組みです。available
になった残高を毎週や毎月自動でお振り込みをしています。
Connect を利用する場合、プラットフォームと子アカウントそれぞれに、pending
とavailable
の残高があります。そして、その流れを決めるのが、決済作成の方法です。
テストの時に、4 営業日も待たないと Transfer のテストができないのか、というお問い合わせをいただきますが、そのようなときには source
をtok_bypassPending
とすると、pending
をスキップできますのでお試しください: https://stripe.com/docs/testing#cards-responses
##マイナス残高について
返金やチャージバックなどは、残高を減らしていきます。すでに入金された決済について、後日返金処理をするなどにより、アカウント上の残高がマイナスになることがあります。このような場合には、次の決済で相殺されることになります。
しかし、継続してアカウント残高がマイナスになってしまった場合、最終的に誰がその責任をとるかというと、アカウントタイプにより異なってきます。
Standard アカウントの場合は 子アカウントが責任を負い、Custom アカウントの場合はプラットフォームが責任を負います。そのため、必要に応じてアカウントの残高を確認しておく必要があります。
balance = stripe.Balance.retrieve(
stripe_account=CONNECTED_STRIPE_ACCOUNT_ID
)
より詳しくは、こちらのドキュメントをご確認ください: https://stripe.com/docs/connect/account-balances
#Connect で日本以外の子アカウントを通して多通貨決済をする
https://stripe.com/docs/connect/currencies
Connect を使うと、海外展開も迅速にできます。Stripe 対応国あれば、その国の法人や個人をすぐに子アカウントすることができます: https://stripe.com/global
例えば、Kickstarter の場合、プラットフォームはアメリカで、子アカウントであるプロジェクトオーナーはアメリカだけではなく、イギリス、オーストラリアや日本など様々な国で、プロジェクトオーナーとして登録されます。
さて、このようなときに、通貨はどのように利用されるか、という疑問が湧きます。
- Direct と Destination Charges => 子アカウントの国の通貨を利用します
- Separate charges and transfers => プラットフォームの通貨になりますが、
on_behalf_of
パラメータの場合のみ、そこで指定したアカウントの通貨が利用されます
ここで重要な用語の解説をします。
- 決済通貨: 顧客が支払う通貨
- 振込み通貨: 銀行口座へ振込む通貨
通貨換算は、決済通貨と振込み通貨が異なる場合に起こります。
決済通貨は130以上あり、振込み通貨は各国によって異なりますので念のため確認をおすすめします。
下記の例では、プラットフォームは全て日本(振込み通貨は JPY)を前提にしています。
##例1
決済は JPY、プラットフォームの振込み通貨は JPY、子アカウントの振込み通貨は USD のケース。
JPY で決済すると、子アカウントへ送金される資金は USD へ換算されます。Direct charges では、プラットフォーム手数料(application_fee
)は JPY となり、Destination charge では USD でプラットフォームに残高として計上されます。
###Direct charge
例えば、10000 JPY の決済を、US 子アカウントで行い、application_fee
を1000 JPY のケースです。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="jpy",
source="tok_visa",
application_fee=1000,
stripe_account="{US Standard Account ID}"
)
子アカウントでは、決済がまず USD に変換されます。application_fee と Stripe fee ともに USD で計算され、最終的に 77.61 USD が残高として残ります(レートは決済時のものが利用されます)。
###Destination charge
10000円の決済を USアカウントに対してDestination charge をします。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="jpy",
source="tok_visa",
description="JPY決済 on US Custom account",
destination={
"amount": 8000,
"account": "{US Custom Account ID}",
}
)
プラットフォーム側では、10000円がまず 88.55 usd に変換され、US アカウントの手数料率2.9% + 0.3 usd が Stripe fee (88.55 * 2.9% + 0.3 = 2.87) として計算されます。
そして、Charge を作成した時にしていた “destination[amount]=8000” に相当する 70.84 USD が US 子アカウントへ送金されます。
最終的にこの決済でプラットフォームに残る残高は、14.84 USD (=85.68-70.84) となります。
子アカウントは、70.84 USD をそのまま得ることになります。
##例2
決済は USD、プラットフォームの振込み通貨は JPY、子アカウントの振込み通貨は JPY のケース。
このケースでは、Direct、Destination Charge 問わず、日本円に換算された残高がプラットフォームに残ります。
###Direct charge
例えば、100 USD の Direct charge を 日本の子アカウントで行い、10 USD の application_fee
を指定したとします。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="usd",
source="tok_visa",
application_fee=1000,
stripe_account="{JP Standard Account ID}"
)
プラットフォームには、10 USD に相当する JPY がプラットフォームに application_fee(プラットフォーム手数料)として残ります。
子アカウントでは、100 USD が JPY に換算され、10,846 JPY となります。この金額に対して、Stripe fee、application_fee が差し引かれた金額が残ります。
###Destination charge
100 USD を日本の Custom アカウントに対して Destination charge をし、80 USD を送金するという決済です。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="usd",
source="tok_visa",
description="USD決済 on JP Custom account",
destination={
"amount": 8000,
"account": "{JP Custom Account ID}",
}
)
まず、プラットフォーム側では、100 USD が 10,846 JPY に換算され、それに対して Stripe fee手数料がかかります。
そして、80 USD に相当する 8677 JPY が Custom アカウントに送金されます。
したがって、プラットフォームには 10456-8677=1799 JPY の残高が増えます。
子アカウントには、8677 JPY の残高が増えます。
##例3
決済は米国ドル, プラットフォームの振込み通貨は日本円、子アカウントの振込み通貨は米国ドルのケース。
子アカウントへ配分される資金は米国ドルになります。Direct chargeは、application feeが日本円に換算されます。Destination charge の場合は米国ドルでプラットフォームに残ります。
###Direct charge
100 USD の決済を、US の Standard Account 上で行い、application fee を 10 USD とする。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="usd",
source="tok_visa",
application_fee=1000,
stripe_account="{US Standard Account ID}",
description="子アカウント=US(Standard),Direct Charge in USD"
)
プラットフォームには、application_fee
で指定した 10 USD に相当する 1085 JPY が残高として残ります。
子アカウントの振込みの通貨は USD なので、100 USD がそのまま計算に使われます。100 USD から Stripe 手数料、application fee が引かれた 86.80 USD が残高として残ります。
###Destination charge
100 USD の決済を行い、 US アカウントを Destination に指定し 80 USD を送金するケース。
stripe.api_key = '{プラットフォームのSecret Key}'
charge = stripe.Charge.create(
amount= 10000,
currency="usd",
source="tok_visa",
description="USD決済 on US Custom account",
destination={
"amount": 8000,
"account": "{US Custom Account ID}",
}
)
プラットフォーム側でも、子アカウント側でも USD で処理されます。100 USD に対して Stripe 手数料が引かれます。
そして、Custom アカウントへの 80 USD 送金されますので、結果としてプラットフォームには、96.80 - 80.00 = 16.80 USD の残高が増えることになります。
また、子アカウントでは、80 USD の残高が増えます。
プラットフォームが日本でも、Destination charge を利用すると USD で残ることがあるということは、米国に銀行口座がないと振り込みされないのか、という疑問が湧きます。しかし、それはコンバート(換算)ができます。
##残高のコンバート(換算)
日本以外の国の子アカウントを登録して Destination charge をすると、プラットフォームの残高には自身の振込み通貨(JPY)ではない通貨で、残高が残ることになります。
例えば、利用可能な残高に 300 EUR 残っていたらどうなるでしょうか。
プラットフォームは JPY の銀行口座しか持っていない場合、手動で Payout を行います。
stripe.Payout.create(
amount=30000,
currency="eur",
)
上記のように 300 EUR の入金をリクエストすると、処理した時点のレートで円換算され、JPY で入金処理がなされます。
より詳しくはこちらのドキュメントにあります: https://stripe.com/docs/connect/currencies
#開発前・開発中に確認しておきたいこと
ここまで実装の方法や概念を説明してきましたが、ビジネスサイドの部分でも検討しておいた方がいいことがあります。過去のユーザさんからお話を伺うと、やはりこの部分は決めておいたほうが良い、という声を聞きますので、いくつか紹介します。
- 返金ポリシー
- 子アカウントへの入金タイミング
- 子アカウントが負担するプラットフォーム手数料の設定
- 運用後のユーザーサポート
- 子アカウントへの本人確認の説明と本人確認のステータスのトラッキング
- 正確な銀行情報の取得の徹底
- 不正利用対策やチャージバックの理解
#その他にも重要なこと
- Webhook: https://stripe.com/docs/connect/webhooks
- リリース前のチェックリストや不正対策など: https://stripe.com/docs/connect/best-practices
この記事が参考になると幸いです。
何か開発中に技術的な内容で問い合わせたいという場合には、プラットフォームのアカウント(ダッシュボード)にログインし、サポートフォームからお問い合わせください。日本語でサポートしています! https://support.stripe.com/email
#用語解説
- 決済: Chargeと表現されており、お客さまが支払うこと
- 入金: Payoutで、それぞれのアカウントの銀行口座 (external account) への入金
- 送金: Transferで、プラットフォームから子アカウントへの残高の移動
- 子アカウント: Connected accountで、プラットフォームを利用してサービスを提供するアカウント。資金の受け手でもある。
- 残高: 決済金額からfeeなどを引いた金額
- 本人確認: ID Verification のこと。Stripe は従来のような事業審査がないので、このプロセスが審査と巷では呼ばれることもありますが、カード利用可否の審査とは全く別ものである。マネーロンダリングや変な組織ではないかを確認するためのプロセス