我们正在将3D安全结帐与我们当前的订阅计费解决方案集成在一起。我们提供7个月免费试用的月租计划。对于集成,我们使用SetupIntent确定客户的卡信息是否需要3D安全授权。使用需要3D安全的Stripe测试卡,我们在结帐页面的javascript中调用handleCardSetup()
函数。然后,在成功授权之后,将客户的付款方式附加到客户。然后继续结帐,我们创建订阅。我们在订阅上展开latest_invoice.payment_intent
。
“ SetupIntents是自动为不需要初始付款的订阅创建的。如果需要身份验证和授权,则也会执行它们。如果成功或不需要,则不需要任何操作,并且subscription.pending_setup_intent字段为空。”
当我查看调用Subscription.create(params)
的响应时,发现pending_setup_intent
字段等于null
。但是,当在Stripe的仪表板上查看预订时,我看到尝试对卡充值的尝试返回了402
错误,并显示以下响应:
{
"error": {
"code": "subscription_payment_intent_requires_action",
"message": "Payment for this subscription requires additional user action before it can be completed successfully. Please refer to the use of the `enable_incomplete_payments` parameter here: https://stripe.com/docs/billing/lifecycle#incomplete-opt-in",
"type": "card_error"
}
}
有什么作用?我在某个地方错过了一步吗?当前,我们正在使用Stripe API的最新版本:2019-05-16
。我已经附加了用于创建SetupIntent
,将PaymentMethod
附加到Customer
以及创建Subscription
的代码。如果我的代码中有任何错误,请告诉我。
SetupIntent:
public static String createSetupIntent() {
try {
Map<String, Object> setupIntentParams = new HashMap<>();
ArrayList<String> paymentMethodTypes = new ArrayList<>();
paymentMethodTypes.add("card");
setupIntentParams.put("payment_method_types", paymentMethodTypes);
SetupIntent setupIntent = SetupIntent.create(setupIntentParams);
return setupIntent.getClientSecret();
} catch (AuthenticationException | InvalidRequestException | ApiConnectionException | ApiException ex) {
throw new Error("Unable to create SetupIntent", ex);
} catch (StripeException ex) {
throw new Error("Unable to create SetupIntent", ex);
}
}
Javascript:
var customerInfo = {
payment_method_data: {
billing_details: {
name: document.getElementById('cardholder_name').value,
address: {
postal_code: document.getElementById('cardholder_zip').value
}
}
}
};
stripe.handleCardSetup(clientSecret, card, customerInfo).then(function (result) {
if (result.error) {
setStripeError(result.error);
hideLoading('hosted_content');
} else {
var paymentMethodId = result.setupIntent.payment_method;
$.post({
url: backendURL + 'attachpaymentmethod',
data: {payment_id: paymentMethodId},
success: function (response) {
document.getElementById('payment-form').submit(); //sends a post to endpoint that handles creating subscription
},
error: function (response) {
hideLoading('hosted_content');
setStripeError(response.responseJSON.error);
}
});
}
});
付款方式:
public static void updatePaymentMethod(User user, String paymentMethodId) throws CardException {
Customer customer = getCustomer(user); //Retrieves customer if user has stripeId, otherwise create a new customer
try {
PaymentMethod paymentMethod = PaymentMethod.retrieve(paymentMethodId);
Map<String, Object> params = new HashMap<String, Object>();
params.put("customer", customer.getId());
paymentMethod.attach(params);
} catch (AuthenticationException | InvalidRequestException | ApiConnectionException | ApiException ex) {
throw new Error("Unable to update Stripe payment method", ex);
} catch (StripeException ex) {
throw new Error("Unable to update Stripe payment method", ex);
}
}
订阅:
Map<String, Object> planItem = new HashMap<>();
planItem.put("plan", planId);
Map<String, Object> items = new HashMap<>();
items.put("0", planItem);
List<String> expandList = new LinkedList<String>();
expandList.add("latest_invoice.payment_intent");
Map<String, Object> subscriptionOptions = new HashMap<>();
subscriptionOptions.put("customer", user.getStripeId());
subscriptionOptions.put("trial_period_days", trialDays);
subscriptionOptions.put("items", items);
subscriptionOptions.put("expand", expandList);
try {
Subscription subscription = Subscription.create(subscriptionOptions);
System.out.println(subscription); //pending_setup_intent is equal to null
} catch (AuthenticationException | InvalidRequestException | ApiConnectionException | ApiException ex) {
throw new Error("Unable to create Stripe subscription", ex);
} catch (StripeException ex) {
throw new Error("Unable to create Stripe subscription", ex);
}
答案 0 :(得分:1)
我与Stripe支持取得联系。他们告诉我,我使用的测试卡的目的是要求每笔交易都具有3DS身份验证。这意味着即使我在对卡进行身份验证之后也保存了它,除非经过身份验证,否则每次使用该卡都会被拒绝。因此,我的解决方案是使用另一种测试卡,该测试卡只需要进行一次身份验证,然后将在每次使用后得到批准。
此外,根据我读过here的有关SCA的一些文档,在SCA所需卡上的重复交易是免税的,只需要进行一次身份验证。因此,建议使用只需要认证一次的测试卡,因为它的行为更接近于开始执行SCA时的行为。