【问题标题】:Stripe Elements card.mount function error after svelte onMount() firessvelte onMount() 触发后 Stripe Elements card.mount 函数错误
【发布时间】:2020-10-24 16:15:40
【问题描述】:

Same issue with other frontend framework and it fixed in some

我正在尝试在 Sapper 应用中使用条带。 Stripe 需要使用您在页面顶部引用的安全 stripe.js 发送信用卡数据。我使用 svelte onMount() 是因为使用他们的脚本进行条带提交数据并且不涉及服务器。

单击购物车组件中的结帐按钮后,我到达了此付款组件,该组件使用 goTo 将我定向到此付款页面/组件:

function checkout(){ 
// handle shopping cart items   
await goto('./checkout/pay');      
  }    
  navigateAndSave()
   }

我的支付组件有以下代码来收集信用卡数据:

    onMount(async () => {
  var stripe = await Stripe('pk_test....');
  // call stripe.elements which will create the credit card fields 
  // use the fields for card #, expiration and cvv
  var elements = await stripe.elements();
  var card =  await elements.create('card');
  // mount the card to the dom
  card.mount("#card-element");

  card.on('change', ({error}) => {
   // code the validate the credit card number, expiration date and other data.
  });  //end of card.on fn

  // code to charge the card. Call

    // now that you mounted the stripe credit card Elment. Collect credit
    // card details and submit it to stripe to process the payment using
    // their api confirmCardPayment
    stripe.confirmCardPayment(client_secret, {
  payment_method: {
   // the stripe card element has the credit card data
  card: card,
  billing_details: {
  name: 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
  }
  }
  }).then(function(result) {
  if (result.error) {
  console.log(result.error.message);
  } else {
  if (result.paymentIntent.status === 'succeeded') {
         // update db, send emails to customer and admin...etc
  }
  }
  });

  // End of submit card information code
   

  } // end onMount()

我的html表单是:

    <svelte:head>
  <script src="https://js.stripe.com/v3/"></script>
</svelte:head>


<h1> clientSecret Checkout </h1>


<form on:submit|preventDefault={onMount}>
  <div id="card-element">
    <!-- Elements will create input elements here -->
  </div>

  <!-- We'll put the error messages in this element -->
  <div id="card-errors" role="alert"></div>

  <button id="submit">Pay </button>
</form>

当我通过填写所有字段(iframe 来自条纹)提交付款表单并单击付款按钮时,我收到以下错误 未捕获(承诺中)IntegrationError:我们无法从指定的元素中检索数据。 请确保您尝试使用的元素仍处于挂载状态。

我看到卡片字段并输入了所需的卡片详细信息,但错误显示该元素未安装或我正在使用的元素未安装。所以在我看来,这与安装组件有关。

任何了解 svelte、组件安装的人都应该能够帮助解决这个问题。在阅读了 vue、react 和 angular 中的一些其他类似问题后,我意识到这是安装前端的具体问题,但我还不能用 svlete 弄清楚。

在 Svelte/sapper 中安装 iframe 是否存在问题? 查看了 sapper preload fn 但我如何在我的 onMount() 中访问卡是我面临的另一个问题。如果我在预加载中放入任何内容,我如何访问卡?

有什么办法吗?

【问题讨论】:

  • 你试过运行 await tick();作为 onMount() 的第一行? svelte.dev/docs#tick
  • @digby280,是的,试过了,问题仍然存在。

标签: javascript stripe-payments sapper svelte-3 svelte-component


【解决方案1】:

您需要分两个阶段处理:

  1. 安装 Stripe 元素
  2. 提交表单。

目前,您尝试同时执行两次:一次是在安装组件时,另一次是在提交表单时。我无法使用您上面提供的代码重现您的确切问题,因为当我尝试从表单调用 onMount() 时,Sapper 出错。我不确定为什么你没有得到同样的错误。我认为您的错误发生是因为您在提交表单时替换了元素。

当我使用测试卡号时,此代码记录“成功”:

<script>
    import {loadStripe} from '@stripe/stripe-js';
    import { onMount } from 'svelte';

    let stripe = null;
    let card = null;
    let secret = null;

    onMount(async () => {
        stripe = await loadStripe('pk_test_...');

        var elements = await stripe.elements();
        card = await elements.create('card');
        // mount the card to the dom
        card.mount("#card-element");
        secret = await fetch('secret.json').then(resp => resp.json());
    });

    async function handlePayment() {
        // code to charge the card. Call

        // now that you mounted the stripe credit card Elment. Collect credit
        // card details and submit it to stripe to process the payment using
        // their api confirmCardPayment
        console.log(JSON.stringify(secret));
        stripe.confirmCardPayment(secret.client_secret, {
            payment_method: {
                // the stripe card element has the credit card data
                card: card,
                billing_details: {
                    name: 'zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz'
                }
            }
        }).then(function(result) {
            if (result.error) {
                console.log(result.error.message);
            } else {
                if (result.paymentIntent.status === 'succeeded') {
                    // update db, send emails to customer and admin...etc
                    console.log('Success');
                }
            }
        });
    }
</script>

<h1> clientSecret Checkout </h1>

<form on:submit|preventDefault={handlePayment}>
  <div id="card-element">
    <!-- Elements will create input elements here -->
  </div>

  <!-- We'll put the error messages in this element -->
  <div id="card-errors" role="alert"></div>

  <button id="submit">Pay </button>
</form>

【讨论】:

  • 感谢您的帮助。这就是这里的确切问题。我不得不将这两个 fn 分开,但后来我遇到了另一个问题:handlesubmit(in your code) fn 无法访问卡,它必须在 onMount() 范围内才能访问卡(创建和挂载的条带该元素必须与提交卡片详细信息的实例相同)但如果句柄提交 fn 在 onMount() 内部,您如何在表单中添加引用?我可以在 onClick 旁边添加 onSubmit 吗?我会尝试并再次发回这里,以便将来遇到此问题的任何人都可以使用它。
  • 我认为你只需要在组件范围内声明卡,而不是在 onMount() 回调内。再看看我的代码。您会注意到卡在 onMount() 之前声明,以便可以从 handlePayment() 访问同一张卡。
  • 一切正常。感谢您的帮助。
猜你喜欢
  • 2018-11-10
  • 2019-09-21
  • 2019-05-25
  • 2021-07-22
  • 2022-12-18
  • 2020-05-05
  • 2019-11-07
  • 1970-01-01
  • 2021-10-04
相关资源
最近更新 更多