我第一次在我的网站上实施条纹订阅,但在付款和请求 3ds 方面遇到问题。
在写作之前我仔细阅读了 stripe 文档,特别是:
https://stripe.com/docs/ payments/accept-a- payment-deferred?platform=web&type=subscription https://stripe.com/docs/billing/subscriptions/build-subscriptions?ui=elements#collect- payment https://stripe.com/docs/billing/subscriptions/overview
我读了很多这样的答案,比如 具有订阅和试用期的 Stripe 支付元素 使用 SCA 身份验证的 Stripe 创建订阅 使用 Stripe 测试订阅试用期
就我而言我希望用户立即输入所有信用卡数据,以便立即在stripe上创建客户、付款方式和订阅,然后留下试用期(我希望是12小时,但是也许 stripe 至少有 2 天)。 测试结束时我希望付款能够完全自动进行,但到目前为止,在测试环境中,我发现我的未付费订阅被标记为“逾期”,这是由于 3DS 的原因。我发现发票. payment_action_required 和“... xxx 欧元发票的付款需要用户进行验证步骤”。
我读到,3DS 的要求可能取决于银行,但我想知道:大多数热门网站如何在不要求用户返回网站并输入 3DS 的情况下接收订阅付款?
是否可以通过某种方式,在我的客户输入卡详细信息时立即向他们索要 3DS,并在试用期结束时自动扣除金额?
这是我的后端代码:
/** create new customer */
export const stripeCustomerCreate = async (customer: StripeCustomerCreateReq): Promise<StripeCustomerCreateRes> => {
const client = await stripeClient();
let customerData: Stripe.CustomerCreateParams = {
address: customer.address,
description: customer.description,
email: customer.email,
name: customer.name,
phone: customer.phone,
shipping: customer.shipping,
};
if (customer.paymentMethod) {
customerData = {
...customerData,
payment_method: customer.paymentMethod,
invoice_settings: {
default_payment_method: customer.paymentMethod,
},
};
}
const newCustomer: Stripe.Customer = await client.customers.create(customerData);
return newCustomer;
};
订阅创建
export const stripeSubscriptionCreate = async (
subscriptionReq: StripeSubscriptionCreateReq,
): Promise<StripeSubscriptionCreateRes> => {
try {
const { customerId, priceId } = subscriptionReq;
if (!customerId || !priceId) throw new Error('Missing data');
const client = await stripeClient();
const subscription = await client.subscriptions.create({
customer: customerId,
items: [{ price: priceId }],
payment_behavior: 'default_incomplete',
payment_settings: {
payment_method_options: {
card: {
request_three_d_secure: 'any',
},
},
payment_method_types: ['card'],
save_default_payment_method: 'on_subscription',
},
trial_period_days: 1,
expand: ['latest_invoice.payment_intent', 'pending_setup_intent'],
});
const pendingSetupIntent = subscription.pending_setup_intent as Stripe.SetupIntent | null;
const invoice = subscription.latest_invoice as Stripe.Invoice | null;
const paymentIntent = invoice?.payment_intent as Stripe.PaymentIntent;
let resData: StripeSubscriptionCreateRes = {
success: true,
subscriptionId: subscription.id,
type: '',
clientSecret: '',
};
if (pendingSetupIntent !== null) {
resData.type = 'setup';
resData.clientSecret = pendingSetupIntent.client_secret;
} else {
resData.type = 'payment';
resData.clientSecret = paymentIntent.client_secret;
}
return resData;
} catch {
return { success: false };
}
};
前端(反应)
const PaymentContainer: FunctionComponent<PaymentContainerProps> = ({ type }) => {
const stripe = useStripe();
const stripeElements = useElements();
const handleSubmit = async (event: FormEvent) => {
event.preventDefault();
if (!stripe || !stripeElements) {
return;
}
const confirmOptions = {
elements: stripeElements,
confirmParams: {
return_url: `${window.location.origin}${buildRoute("ACCOUNT.WELCOMECOMPLETE")}`,
},
};
const result =
type === "setup"
? await stripe.confirmSetup(confirmOptions)
: await stripe.confirmPayment(confirmOptions)
if (result.error) {
// Show error to your customer (for example, payment details incomplete)
console.log(result.error.message);
} else {
// Your customer will be redirected to your `return_url`. For some payment
// methods like iDEAL, your customer will be redirected to an intermediate
// site first to authorize the payment, then redirected to the `return_url`.
}
};
return (
<form onSubmit={handleSubmit}>
<PaymentElement />
<Button type={"submit"} disabled={!stripe}>
Submit
</Button>
</form>
);
};
您的订阅请求 3DS 的原因可能是因为您在创建订阅时设置了 request_third_d_secure=any。当您包含该参数时,如果 3DS 身份验证适用于卡,Stripe 会要求您的客户执行身份验证才能成功完成付款。请参阅https://stripe.com/docs/ payments/3d-secure#manual- Three-ds
如果您省略
request_three_d_secure
,订阅续订应继续进行,而无需请求 3DS。