微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用 React Elements 在 Formik 向导中提交 Stripe Payment?

如何解决如何使用 React Elements 在 Formik 向导中提交 Stripe Payment?

我正在使用 Formik 和 Material-UI 中的步进器在 React 中创建一个多步骤表单。那部分正在工作(终于!),我大致了解如何工作。第 1 步是账单地址,第 2 步是选择订阅计划,第 3 步是使用 Stripe 及其 CardElements 付款。这就是我偏离轨道的地方。

我在应用程序中加载了 Stripe,因此它被包装并可供我的表单使用。都好。我可以在单独测试时成功调用 Stripe 方法

我的 Formik 外层在这里

<Formik
    {...props}
    validationSchema={currentChild.props.validationSchema}
    onSubmit={async (values,helpers) => {
      if (isLastStep()) {
        await props.onSubmit(values,helpers);
        setCompleted(true);
      } else {
        setStep((s) => s + 1);
        helpers.setTouched({});
        if (step === 1) {
          await props.getCustomerId(values.billingEmail);
        }
      }
    }}
  >
  {... map over the steps,then the Back/Next/Submit buttons}
  </Formik>

在 formStepper 创建时,我调用 useStripe()useElements() 并创建一个 CardElement,它被传递到第 3 步:

    const stripe = useStripe();
      const elements = useElements();
      let stripeCard = CardElement;
    
    <FormikStepper
                    initialValues={{ ...billingValues }}
                    onSubmit={(values,helpers) => {
                      createCustomer(values); //successfully sends formValues to be processed
                    }}
                    // I tried adding this here,but it isn't accessible inside the steps
// ETA: I put stripeProps inside the FormikStepper,which passes its properties down to the FormikStep inside. For non-Formik users,this works for the onBlur,onFocus,etc. as well as passing the initialValues.  Basically,I was hoping the card element Could hitch a ride
                    stripeProps={{ card: stripeCard }}
                    getCustomerId={async (billingEmail) => {
                      await fetchCustomerId(billingEmail);
                    }}
                  >
                    <FormikStep
                      label="Billing Info"
                      validationSchema={object({ ...validationSchemaUsingYup })}
                    >
                      <Grid container item spacing={1}>
                        <CompanyProfile />
                      </Grid>
                    </FormikStep>
        
                    <FormikStep label="Choose Subscription">
                      <Grid container item spacing={1}>
                        <ChooseSubscription />
                      </Grid>
                    </FormikStep>
        
                    <FormikStep label="Review & Pay">
                      <Grid container item spacing={1}>
                        <StripePayment card={stripeCard} />
                      </Grid>
                    </FormikStep>
                  </FormikStepper>

在第 3 步中,我可以按预期呈现和使用 CardElement:

<props.card
    options={{
      style: {...styling}
    }}
  />

我的困惑在于如何访问此元素以将数据提交给 Stripe??如何访问我传递到第 3 步的道具并使用它来处理付款?
我尝试将 Stripe 函数放在步骤 3 的函数中,但它们从未被调用,因为 onSubmit 函数位于步骤的父级上。我不能在不破坏使用条纹元素的安全方面的情况下将卡号放入 Formik initialValues。我能得到的最接近的就是这个错误

Warning: An unhandled error was caught from submitForm() IntegrationError: A valid Element name must be provided. Valid Elements are:
  card,cardNumber,cardExpiry,cardCvc,postalCode,paymentRequestButton,iban,idealBank,p24Bank,auBankAccount,fpxBank; you passed: object.

响应评论的更新: stripeProps 尝试将信息打包到 FormikStepper 中,从而将 props 传递给子级 FormikSteponSubmit 调用 createPaymentMethod,如下所示:

    async function createPaymentMethod(
    values,stripeData = stripeCard,customer = customerId
  ) {
    if (customer === undefined) {
      customer = fetchCustomerId(values.billingEmail);
    }

    return stripe
      .createPaymentMethod({
        type: "card",card: elements.getElement(stripeData),//no errors with CardElement,but not sure that's the SAME element from the form
      })
      .then((result) => {
        if (result.error) {
          console.log(result.error);
        } else {
          createSubscription({
            customer: customer,paymentMethodId: result.paymentMethod.id,items: [
              {
                price: values.TCPlan,quantity: values.TCPlanQuantity,},],});
        }
      })
      .catch((err) => console.log(err));
  }

  // Step 2 of the Stripe process;
  // Called if createPaymentMethod is error-free
  function createSubscription({ customer,paymentMethodId,items }) {
    console.log(customer,items);
    let created = fetch(
      "https://xxxxxx.amazonaws.com/xxx/xxxx",// My API Gateway endpoint
      {
        method: "post",headers: {
          "Content-type": "application/json",body: JSON.stringify({
          customerId: customer,paymentMethodId: paymentMethodId,priceId: items,}),}
    );

    created
      .then((response) => {
        console.log(response.json());
      })
      // varIoUs error-handling offered by Stripe...
  }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。