Python Stripe - 创建 Connect & Customer 用户 - 借记卡并将钱转入银行账户
Python Stripe - Create Connect & Customer users - charge card and transfer money into a bank account
我在 Stripe 中有两种类型的用户:
- 最终客户(支付并收到 product/service);
- Connect 用户(将拥有 Connect 帐户并将提供 products/service);
让我们假设在下面的示例中 user 是一个模型实例 (Django):
# Connect Account
instance = stripe.Account.create(
type="custom",
country="PL",
email=user.email,
default_currency="pln",
business_type="individual",
requested_capabilities=["card_payments", "transfers",],
individual={
"first_name": user.first_name.strip(),
"last_name": user.last_name.strip(),
"email": user.email,
"dob": {
"day": user.profile.date_of_birth.day,
"month": user.profile.date_of_birth.month,
"year": user.profile.date_of_birth.year,
},
"phone": user.profile.phone_number,
"address": {
"city": user.city.strip(),
"postal_code": user.profile.postal_code.strip(),
"country": "PL",
"line1": user.profile.address.strip(),
},
},
)
# Customer Account
instance = stripe.Customer.create(
email=user.email,
description="desc",
name=user.get_full_name.strip(),
phone=user.profile.phone_number.strip(),
)
那两个 API 调用正常。然后我可以为新用户检索唯一的 Stripe ID:
stripe_customer_id = instance.get("id")
对于stripe.Account类型,我需要提供身份验证:身份证正反面(举例):
document_images_data = [
"data:image/png;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
"data:image/png;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
]
_front = stripe.File.create(
purpose="identity_document",
file=Base64ImageField().to_internal_value(base64_data=document_images_data[0]),
stripe_account=stripe_customer_id,
)
_back = stripe.File.create(
purpose="identity_document",
file=Base64ImageField().to_internal_value(base64_data=document_images_data[1]),
stripe_account=stripe_customer_id,
)
individual = {
"verification": {
"document": {"front": _front.get("id"), "back": _back.get("id")},
"additional_document": {"front": _front.get("id"), "back": _back.get("id")},
}
}
然后我需要将上传的文件附加到stripe.Account实例:
stripe.Account.modify(stripe_customer_id, individual=individual)
并通过 API:
接受 Stripe 条款
stripe.Account.modify(stripe_customer_id, tos_acceptance={"date": int(time.time()), "ip": user.user_ip,})
成功创建stripe.Account实例后,我可以在Stripe的仪表盘上看到,还有两件事需要填写,这样账户就可以完全验证:
- 行业
- 商业网站
有没有办法以某种方式在 API 调用中填充这些数据?更重要的是,我正在尝试创建一个 个人 类型的帐户,那么为什么还需要填写这两件事?
从现在开始,我有两个用户,我想添加一张 Card 到 Customer Account 和 银行账户到连接账户。
在这两种情况下,我都使用 令牌 提供的 card/bank 帐户详细信息,就像这样(条纹测试 card/bank 帐户):
stripe.Customer.create_source(stripe_customer_id, source="tok_amex") # example token card details
stripe.Account.create_external_account(
stripe_customer_id,
external_account="btok_1H7J0nHksFGR44vruZzOpnnD", # example token bank account details
)
现在,假设我要向 Customer card 和 transfer 收费将钱存入 Connect Account.
据我从文档中了解到,应该是:
stripe.Charge.create(
amount=10000,
currency="pln",
customer=stripe_customer_id, # stripe.Customer unique Stripe ID
description="some desc",
)
此操作也有效,因为我可以在 Stripe 的仪表板上看到结果。
现在我想将这些钱转入连接账户:
stripe.Transfer.create(amount=10000, currency="pln", destination=connect_account_stripe_id)
尽管我在 stripe.Customer 余额中添加了一些积分,但我得到了:
You have insufficient funds in your Stripe account. One likely reason you have insufficient funds is that your funds are automatically being paid out
如何启用手动传输?最重要的问题是——这是一种正确的方法还是应该以不同的方式处理整个过程?提前致谢!
当您处理针对客户 (stripe.Charge.create
) 的付款时,这会将资金添加到您的平台帐户余额中。资金最初是 pending
for some time(https://stripe.com/docs/payouts#standard-payout-timing).
调用 /v1/transfers (stripe.Transfers.create
) 试图从您的 available
余额中提取资金并将其转移到目标 Stripe 帐户。如果您没有 available
余额,它将失败,这里很可能就是这种情况。
如果您的平台启用每日自动付款(默认设置),您将永远不会实际拥有available
余额。那是因为 Stripe 会将资金直接从您的 pending
余额转移到您的支出中,这样您就可以尽快获得这笔钱,这是大多数账户想要的(作为具有这种资金流的 Connect 平台,您是更高级一点)。
如果你想进行这种转移,我建议按顺序执行以下操作:
- 如果 'delay' 客户付款与支付到关联帐户之间的 'delay'(例如,提供服务需要多长时间)少于 7 天,您可以只使用 Destination费用(https://stripe.com/docs/connect/destination-charges) with auth-and-capture(https://stripe.com/docs/payments/capture-later)。与单独收费和转帐相比,工作量要少得多,而且您不必考虑太多余额。
- 否则,您将需要:
- 调用
stripe.Transfer.create
时使用 source_transaction
: https://stripe.com/docs/connect/charges-transfers#transfer-availability 。这让转账立即成功,收到费用中的资金将在可用时转移到关联账户。
- 或者,将您的平台设置为手动支付:https://dashboard.stripe.com/settings/payouts 随着时间的推移,您将从您的支付中积累
available
余额。然后,您可以直接从该余额进行转账,例如您在问题中分享的 API 电话。在测试模式下,您可以使用特殊的测试卡来模拟拥有 available
余额而无需等待几天。
And the most important question - Is it a proper approach or the entire process should be handled in different way?
这个模型(有一个市场,平台的每个用户都有一个 Stripe 客户和一个与之关联的 Stripe 帐户,您将它们绑定在一起)很正常,但构建起来很棘手。同样,您实际上只是在构建一个标准的“单独收费和转账”集成:https://stripe.com/docs/connect/charges#separate-charges-transfers 但是您正在构建 Stripe 上最复杂的东西之一(自定义连接 + 单独的收费和转账),所以它有点一项事业。
我会尽量简化它,除非你绝对不能,否则我会使用目的地费用,并使用 Express 或 Stripe 的自定义帐户托管入职 (https://stripe.com/docs/connect/connect-onboarding),除非你 真的需要给这个贴上白标签。
此外,您应该在付款部分使用 PaymentIntents(https://stripe.com/docs/payments/accept-a-payment),而不是 Charge.create
和令牌,因为它们不支持在欧洲很重要的 3D Secure,但也许可以使用它们来测试事物的连接方面。
我在 Stripe 中有两种类型的用户:
- 最终客户(支付并收到 product/service);
- Connect 用户(将拥有 Connect 帐户并将提供 products/service);
让我们假设在下面的示例中 user 是一个模型实例 (Django):
# Connect Account
instance = stripe.Account.create(
type="custom",
country="PL",
email=user.email,
default_currency="pln",
business_type="individual",
requested_capabilities=["card_payments", "transfers",],
individual={
"first_name": user.first_name.strip(),
"last_name": user.last_name.strip(),
"email": user.email,
"dob": {
"day": user.profile.date_of_birth.day,
"month": user.profile.date_of_birth.month,
"year": user.profile.date_of_birth.year,
},
"phone": user.profile.phone_number,
"address": {
"city": user.city.strip(),
"postal_code": user.profile.postal_code.strip(),
"country": "PL",
"line1": user.profile.address.strip(),
},
},
)
# Customer Account
instance = stripe.Customer.create(
email=user.email,
description="desc",
name=user.get_full_name.strip(),
phone=user.profile.phone_number.strip(),
)
那两个 API 调用正常。然后我可以为新用户检索唯一的 Stripe ID:
stripe_customer_id = instance.get("id")
对于stripe.Account类型,我需要提供身份验证:身份证正反面(举例):
document_images_data = [
"data:image/png;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
"data:image/png;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",
]
_front = stripe.File.create(
purpose="identity_document",
file=Base64ImageField().to_internal_value(base64_data=document_images_data[0]),
stripe_account=stripe_customer_id,
)
_back = stripe.File.create(
purpose="identity_document",
file=Base64ImageField().to_internal_value(base64_data=document_images_data[1]),
stripe_account=stripe_customer_id,
)
individual = {
"verification": {
"document": {"front": _front.get("id"), "back": _back.get("id")},
"additional_document": {"front": _front.get("id"), "back": _back.get("id")},
}
}
然后我需要将上传的文件附加到stripe.Account实例:
stripe.Account.modify(stripe_customer_id, individual=individual)
并通过 API:
接受 Stripe 条款stripe.Account.modify(stripe_customer_id, tos_acceptance={"date": int(time.time()), "ip": user.user_ip,})
成功创建stripe.Account实例后,我可以在Stripe的仪表盘上看到,还有两件事需要填写,这样账户就可以完全验证:
- 行业
- 商业网站
有没有办法以某种方式在 API 调用中填充这些数据?更重要的是,我正在尝试创建一个 个人 类型的帐户,那么为什么还需要填写这两件事?
从现在开始,我有两个用户,我想添加一张 Card 到 Customer Account 和 银行账户到连接账户。
在这两种情况下,我都使用 令牌 提供的 card/bank 帐户详细信息,就像这样(条纹测试 card/bank 帐户):
stripe.Customer.create_source(stripe_customer_id, source="tok_amex") # example token card details
stripe.Account.create_external_account(
stripe_customer_id,
external_account="btok_1H7J0nHksFGR44vruZzOpnnD", # example token bank account details
)
现在,假设我要向 Customer card 和 transfer 收费将钱存入 Connect Account.
据我从文档中了解到,应该是:
stripe.Charge.create(
amount=10000,
currency="pln",
customer=stripe_customer_id, # stripe.Customer unique Stripe ID
description="some desc",
)
此操作也有效,因为我可以在 Stripe 的仪表板上看到结果。
现在我想将这些钱转入连接账户:
stripe.Transfer.create(amount=10000, currency="pln", destination=connect_account_stripe_id)
尽管我在 stripe.Customer 余额中添加了一些积分,但我得到了:
You have insufficient funds in your Stripe account. One likely reason you have insufficient funds is that your funds are automatically being paid out
如何启用手动传输?最重要的问题是——这是一种正确的方法还是应该以不同的方式处理整个过程?提前致谢!
当您处理针对客户 (stripe.Charge.create
) 的付款时,这会将资金添加到您的平台帐户余额中。资金最初是 pending
for some time(https://stripe.com/docs/payouts#standard-payout-timing).
调用 /v1/transfers (stripe.Transfers.create
) 试图从您的 available
余额中提取资金并将其转移到目标 Stripe 帐户。如果您没有 available
余额,它将失败,这里很可能就是这种情况。
如果您的平台启用每日自动付款(默认设置),您将永远不会实际拥有available
余额。那是因为 Stripe 会将资金直接从您的 pending
余额转移到您的支出中,这样您就可以尽快获得这笔钱,这是大多数账户想要的(作为具有这种资金流的 Connect 平台,您是更高级一点)。
如果你想进行这种转移,我建议按顺序执行以下操作:
- 如果 'delay' 客户付款与支付到关联帐户之间的 'delay'(例如,提供服务需要多长时间)少于 7 天,您可以只使用 Destination费用(https://stripe.com/docs/connect/destination-charges) with auth-and-capture(https://stripe.com/docs/payments/capture-later)。与单独收费和转帐相比,工作量要少得多,而且您不必考虑太多余额。
- 否则,您将需要:
- 调用
stripe.Transfer.create
时使用source_transaction
: https://stripe.com/docs/connect/charges-transfers#transfer-availability 。这让转账立即成功,收到费用中的资金将在可用时转移到关联账户。 - 或者,将您的平台设置为手动支付:https://dashboard.stripe.com/settings/payouts 随着时间的推移,您将从您的支付中积累
available
余额。然后,您可以直接从该余额进行转账,例如您在问题中分享的 API 电话。在测试模式下,您可以使用特殊的测试卡来模拟拥有available
余额而无需等待几天。
- 调用
And the most important question - Is it a proper approach or the entire process should be handled in different way?
这个模型(有一个市场,平台的每个用户都有一个 Stripe 客户和一个与之关联的 Stripe 帐户,您将它们绑定在一起)很正常,但构建起来很棘手。同样,您实际上只是在构建一个标准的“单独收费和转账”集成:https://stripe.com/docs/connect/charges#separate-charges-transfers 但是您正在构建 Stripe 上最复杂的东西之一(自定义连接 + 单独的收费和转账),所以它有点一项事业。
我会尽量简化它,除非你绝对不能,否则我会使用目的地费用,并使用 Express 或 Stripe 的自定义帐户托管入职 (https://stripe.com/docs/connect/connect-onboarding),除非你 真的需要给这个贴上白标签。
此外,您应该在付款部分使用 PaymentIntents(https://stripe.com/docs/payments/accept-a-payment),而不是 Charge.create
和令牌,因为它们不支持在欧洲很重要的 3D Secure,但也许可以使用它们来测试事物的连接方面。