Java 使用定期计费模型更新SCA的条带支付

Java 使用定期计费模型更新SCA的条带支付,java,stripe-payments,stripe-sca,Java,Stripe Payments,Stripe Sca,我目前正在将我的应用程序从使用Stripe Charges API迁移到使用Stripe PaymentIntents API,以遵守SCA法规。我的应用程序是一个定期计费模式的订阅服务,因此我一直在关注迁移文档的“健身房会员”示例,以及其他相关文档和参考资料 我在前端使用条带元素来捕获定制表单上的支付细节等,然后将条带支付令牌发送到后端进行进一步处理(同步)。前端更新足够简单,我在那里没有问题,但我对后端更新有点困惑 我可以在文档中找到的所有代码示例(通常非常棒)都显示了如何将Charge调用

我目前正在将我的应用程序从使用Stripe Charges API迁移到使用Stripe PaymentIntents API,以遵守SCA法规。我的应用程序是一个定期计费模式的订阅服务,因此我一直在关注迁移文档的“健身房会员”示例,以及其他相关文档和参考资料

我在前端使用条带元素来捕获定制表单上的支付细节等,然后将条带支付令牌发送到后端进行进一步处理(同步)。前端更新足够简单,我在那里没有问题,但我对后端更新有点困惑

我可以在文档中找到的所有代码示例(通常非常棒)都显示了如何将
Charge
调用转换为
PaymentIntent
调用,例如,这个旧的Charge调用:

Map<String, Object> chargeParams = new HashMap<String, Object>();
chargeParams.put("amount", 1099);
chargeParams.put("currency", "eur");
chargeParams.put("source", request.token_id);
Charge.create(chargeParams);
新的
Customer
创建、新的
PaymentSource
创建和新的
Subscription
创建呼叫是否受到SCA拒绝的影响,此时我必须返回客户进行进一步验证

如果是这样,我如何检查客户和PaymentSource呼叫是否有必要这样做,以及如何获取所需的客户机密令牌以发送回前端?Subscription对象确实提供了对具有状态和客户端机密的
SetupIntent
对象的访问,因此我必须检查并使用它们吗


任何带有示例的相关文档链接都会非常有用。

唯一需要SCA的时间是您尝试付款时。在收集客户的付款详细信息(并可选择将其保存为新客户)后,您要求Stripe完成付款。然后,Stripe将联系客户的银行,询问是否可以付款,或者是否需要额外的身份验证

如果银行说不需要额外付款,那么付款成功,一切都很好

如果银行表示需要3DS支票,则您需要通过3DS流运行客户,这基本上是一个2FA步骤,以确保请求付款的人也是持卡人

如果您的客户仍在“会话中”(例如,仍在您的站点上),则您应将新创建的PaymentIntent的客户机密传递给前端,并使用Stripe.js完成2FA步骤并验证付款

如果您的客户处于“非会话状态”(例如,这是一个定期订阅,他们不在您的站点上),则您必须向客户发送电子邮件,让他们返回您的站点以执行3DS步骤(或者您可以使用Stripe)

在您的情况下,当您创建订阅(假设您不使用试用期)时,Stripe将创建一张发票,并附上自动创建的PaymentIntent。您可以通过上的
latest\u Invoice
参数访问此发票。如果需要3DS步骤,PaymentIntent将具有
requires\u action
状态,这意味着您需要让客户返回“会话”以完成付款

在这种情况下,通过托管发票页面,Stripe将自动向您的用户发送电子邮件,以便他们能够完成付款。如果没有托管的invoice页面,您将不得不构建自己的实现,以让用户返回“会话”


创建客户或PaymentMethod时,您无需执行3DS操作,仅当您实际尝试将资金从一个地方转移到另一个地方时才需要执行此操作。

我现在了解了如何判断订阅创建是否需要进一步验证,以及如何检索相关的客户机密,但是如何在3DS身份验证后向订阅创建调用提供新的支付ID。例如,PaymentIntent可能是
params.put(“payment_方法”,request.paymentMethodId);intent=PaymentIntent.create(参数)。。。在重试Subscription.create调用时,是否可以在订阅参数中添加类似的内容?我在文件中没有看到任何相关内容:你想退房
Map<String, Object> createPaymentIntentParams = new HashMap<String, Object>();
createPaymentIntentParams.put("currency", "eur");
createPaymentIntentParams.put("amount", 1099);
createPaymentIntentParams.put("confirm", true);
createPaymentIntentParams.put("confirmation_method", "manual");
createPaymentIntentParams.put("payment_method", request.paymentMethodId);
intent = PaymentIntent.create(createPaymentIntentParams);
Map<String, Object> srchOpts = new HashMap<>();
srchOpts.put("email", userEmail);   

List<Customer> matchingCustomers = Customer.list(srchOpts).getData();
Customer customer = null;
Subscription subscription = null;

if ( matchingCustomers.isEmpty() ){
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("email", userEmail);
    params.put("source", stripeToken);
    customer = Customer.create(params); // potential SCA rejection ??
}
else if (matchingCustomers.size() == 1) {
    customer = matchingCustomers.get(0);
    Map<String, Object> params = new HashMap<String, Object>();
    params.put("source", stripeToken);
    PaymentSourceCollection paymentSources = customer.getSources();
    paymentSources.create(params); // potential SCA rejection ??
}

Map<String, Object> item = new HashMap<String, Object>();
item.put("plan", planId);

Map<String, Object> items = new HashMap<String, Object>();
items.put("0", item);

Map<String, Object> params = new HashMap<String, Object>();
params.put("items", items);

params.put("customer", customer.getId());
subscription = Subscription.create(params); // potential SCA rejection ??