我们正在将 3D 安全结账与我们当前的订阅计费解决方案集成。我们提供 7 天免费试用的月度计划。对于集成,我们使用 SetupIntent 来确定客户的卡信息是否需要 3D 安全授权。使用需要 3D 安全的 Stripe 测试卡,我们handleCardSetup()
在结帐页面的 javascript 中调用该函数。然后在授权成功后,将客户的付款方式附加给客户。然后继续结帐,我们创建订阅。我们扩展latest_invoice.payment_intent
订阅。
根据 Stripe 的文档:
“SetupIntents 是为不需要初始付款的订阅自动创建的。如果需要身份验证和授权,它们也会被执行。如果两者都成功,或者不需要它们,则不需要任何操作,并且订阅.pending_setup_intent 字段为空。”
当我查看 call 的响应时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
。如果我的代码中有任何错误,请告诉我。
设置意图:
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);
}