Stripe 订阅、试用期和 3ds SCA

问题描述 投票:0回答:1

我第一次在我的网站上实施条纹订阅,但在付款和请求 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>
  );
};
stripe-payments subscription recurring-billing
1个回答
0
投票

您的订阅请求 3DS 的原因可能是因为您在创建订阅时设置了 request_third_d_secure=any。当您包含该参数时,如果 3DS 身份验证适用于卡,Stripe 会要求您的客户执行身份验证才能成功完成付款。请参阅https://stripe.com/docs/ payments/3d-secure#manual- Three-ds

如果您省略

request_three_d_secure
,订阅续订应继续进行,而无需请求 3DS。

© www.soinside.com 2019 - 2024. All rights reserved.